@greppleai/grip 0.1.5 → 0.1.7

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 (587) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +1 -1
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/bun/embedded-assets.d.ts.map +1 -1
  6. package/dist/bun/embedded-assets.js.map +1 -1
  7. package/dist/bun/register-bedrock.d.ts.map +1 -1
  8. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  9. package/dist/bun/restore-sandbox-env.js.map +1 -1
  10. package/dist/cli/args.d.ts.map +1 -1
  11. package/dist/cli/args.js.map +1 -1
  12. package/dist/cli/config-selector.d.ts.map +1 -1
  13. package/dist/cli/config-selector.js.map +1 -1
  14. package/dist/cli/file-processor.d.ts.map +1 -1
  15. package/dist/cli/file-processor.js.map +1 -1
  16. package/dist/cli/initial-message.d.ts +1 -1
  17. package/dist/cli/initial-message.d.ts.map +1 -1
  18. package/dist/cli/initial-message.js.map +1 -1
  19. package/dist/cli/list-models.d.ts.map +1 -1
  20. package/dist/cli/list-models.js.map +1 -1
  21. package/dist/cli/session-picker.d.ts.map +1 -1
  22. package/dist/cli/session-picker.js.map +1 -1
  23. package/dist/cli.d.ts.map +1 -1
  24. package/dist/cli.js.map +1 -1
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +2 -0
  27. package/dist/config.js.map +1 -1
  28. package/dist/core/agent-session.d.ts +38 -1
  29. package/dist/core/agent-session.d.ts.map +1 -1
  30. package/dist/core/agent-session.js +289 -154
  31. package/dist/core/agent-session.js.map +1 -1
  32. package/dist/core/auth-guidance.d.ts.map +1 -1
  33. package/dist/core/auth-guidance.js.map +1 -1
  34. package/dist/core/auth-storage.d.ts +4 -0
  35. package/dist/core/auth-storage.d.ts.map +1 -1
  36. package/dist/core/auth-storage.js +3 -10
  37. package/dist/core/auth-storage.js.map +1 -1
  38. package/dist/core/bash-executor.d.ts.map +1 -1
  39. package/dist/core/bash-executor.js +19 -23
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  42. package/dist/core/compaction/branch-summarization.js.map +1 -1
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +9 -2
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/compaction/compression-detection-ledger.d.ts.map +1 -1
  47. package/dist/core/compaction/compression-detection-ledger.js.map +1 -1
  48. package/dist/core/compaction/compression-detector.d.ts +1 -0
  49. package/dist/core/compaction/compression-detector.d.ts.map +1 -1
  50. package/dist/core/compaction/compression-detector.js +10 -21
  51. package/dist/core/compaction/compression-detector.js.map +1 -1
  52. package/dist/core/compaction/compression-economics.d.ts.map +1 -1
  53. package/dist/core/compaction/compression-economics.js.map +1 -1
  54. package/dist/core/compaction/utils.d.ts.map +1 -1
  55. package/dist/core/compaction/utils.js.map +1 -1
  56. package/dist/core/defaults.d.ts.map +1 -1
  57. package/dist/core/diagnostics.d.ts.map +1 -1
  58. package/dist/core/event-bus.d.ts.map +1 -1
  59. package/dist/core/event-bus.js.map +1 -1
  60. package/dist/core/exec.d.ts.map +1 -1
  61. package/dist/core/exec.js.map +1 -1
  62. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  63. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  64. package/dist/core/export-html/index.d.ts.map +1 -1
  65. package/dist/core/export-html/index.js.map +1 -1
  66. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  67. package/dist/core/export-html/tool-renderer.js.map +1 -1
  68. package/dist/core/extensions/loader.d.ts.map +1 -1
  69. package/dist/core/extensions/loader.js.map +1 -1
  70. package/dist/core/extensions/runner.d.ts +3 -0
  71. package/dist/core/extensions/runner.d.ts.map +1 -1
  72. package/dist/core/extensions/runner.js +40 -30
  73. package/dist/core/extensions/runner.js.map +1 -1
  74. package/dist/core/extensions/types.d.ts +21 -1
  75. package/dist/core/extensions/types.d.ts.map +1 -1
  76. package/dist/core/extensions/types.js.map +1 -1
  77. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  78. package/dist/core/extensions/wrapper.js.map +1 -1
  79. package/dist/core/footer-data-provider.d.ts.map +1 -1
  80. package/dist/core/footer-data-provider.js +15 -16
  81. package/dist/core/footer-data-provider.js.map +1 -1
  82. package/dist/core/grip-agent.d.ts.map +1 -1
  83. package/dist/core/grip-agent.js +7 -21
  84. package/dist/core/grip-agent.js.map +1 -1
  85. package/dist/core/grip-manifest.d.ts.map +1 -1
  86. package/dist/core/grip-manifest.js.map +1 -1
  87. package/dist/core/hooks/aggregate.d.ts.map +1 -1
  88. package/dist/core/hooks/aggregate.js.map +1 -1
  89. package/dist/core/hooks/config.d.ts.map +1 -1
  90. package/dist/core/hooks/config.js.map +1 -1
  91. package/dist/core/hooks/executor.d.ts.map +1 -1
  92. package/dist/core/hooks/executor.js.map +1 -1
  93. package/dist/core/hooks/index.d.ts.map +1 -1
  94. package/dist/core/hooks/index.js.map +1 -1
  95. package/dist/core/hooks/matcher.d.ts.map +1 -1
  96. package/dist/core/hooks/matcher.js.map +1 -1
  97. package/dist/core/hooks/trust-store.d.ts.map +1 -1
  98. package/dist/core/hooks/trust-store.js +0 -3
  99. package/dist/core/hooks/trust-store.js.map +1 -1
  100. package/dist/core/hooks/types.d.ts.map +1 -1
  101. package/dist/core/hooks/types.js.map +1 -1
  102. package/dist/core/http-dispatcher.d.ts.map +1 -1
  103. package/dist/core/http-dispatcher.js.map +1 -1
  104. package/dist/core/instruction-resource-loader.d.ts +1 -0
  105. package/dist/core/instruction-resource-loader.d.ts.map +1 -1
  106. package/dist/core/instruction-resource-loader.js +2 -4
  107. package/dist/core/instruction-resource-loader.js.map +1 -1
  108. package/dist/core/keybindings.d.ts.map +1 -1
  109. package/dist/core/keybindings.js +0 -1
  110. package/dist/core/keybindings.js.map +1 -1
  111. package/dist/core/lsp/abort.d.ts.map +1 -1
  112. package/dist/core/lsp/abort.js.map +1 -1
  113. package/dist/core/lsp/client.d.ts.map +1 -1
  114. package/dist/core/lsp/client.js +8 -22
  115. package/dist/core/lsp/client.js.map +1 -1
  116. package/dist/core/lsp/config-loader.d.ts.map +1 -1
  117. package/dist/core/lsp/config-loader.js.map +1 -1
  118. package/dist/core/lsp/config.d.ts.map +1 -1
  119. package/dist/core/lsp/config.js.map +1 -1
  120. package/dist/core/lsp/diagnostics.d.ts.map +1 -1
  121. package/dist/core/lsp/diagnostics.js.map +1 -1
  122. package/dist/core/lsp/file-sync.d.ts.map +1 -1
  123. package/dist/core/lsp/file-sync.js +7 -9
  124. package/dist/core/lsp/file-sync.js.map +1 -1
  125. package/dist/core/lsp/integration.d.ts.map +1 -1
  126. package/dist/core/lsp/integration.js.map +1 -1
  127. package/dist/core/lsp/language-map.d.ts.map +1 -1
  128. package/dist/core/lsp/language-map.js +2 -7
  129. package/dist/core/lsp/language-map.js.map +1 -1
  130. package/dist/core/lsp/manager.d.ts.map +1 -1
  131. package/dist/core/lsp/manager.js +18 -29
  132. package/dist/core/lsp/manager.js.map +1 -1
  133. package/dist/core/lsp/navigation.d.ts.map +1 -1
  134. package/dist/core/lsp/navigation.js.map +1 -1
  135. package/dist/core/lsp/portable-path.d.ts.map +1 -1
  136. package/dist/core/lsp/portable-path.js.map +1 -1
  137. package/dist/core/lsp/refactor.d.ts.map +1 -1
  138. package/dist/core/lsp/refactor.js.map +1 -1
  139. package/dist/core/lsp/transport.d.ts.map +1 -1
  140. package/dist/core/lsp/transport.js.map +1 -1
  141. package/dist/core/messages.d.ts.map +1 -1
  142. package/dist/core/messages.js +30 -1
  143. package/dist/core/messages.js.map +1 -1
  144. package/dist/core/model-registry.d.ts.map +1 -1
  145. package/dist/core/model-registry.js +5 -7
  146. package/dist/core/model-registry.js.map +1 -1
  147. package/dist/core/model-resolver.d.ts.map +1 -1
  148. package/dist/core/model-resolver.js.map +1 -1
  149. package/dist/core/output-guard.d.ts.map +1 -1
  150. package/dist/core/output-guard.js.map +1 -1
  151. package/dist/core/package-manager.d.ts.map +1 -1
  152. package/dist/core/package-manager.js +0 -6
  153. package/dist/core/package-manager.js.map +1 -1
  154. package/dist/core/prompt-templates.d.ts.map +1 -1
  155. package/dist/core/prompt-templates.js.map +1 -1
  156. package/dist/core/provider-display-names.d.ts.map +1 -1
  157. package/dist/core/remote-workspace-protocol/contract.d.ts.map +1 -1
  158. package/dist/core/remote-workspace-protocol/contract.js +4 -2
  159. package/dist/core/remote-workspace-protocol/contract.js.map +1 -1
  160. package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts.map +1 -1
  161. package/dist/core/remote-workspace-protocol/guest-shared-client.js +1 -5
  162. package/dist/core/remote-workspace-protocol/guest-shared-client.js.map +1 -1
  163. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts.map +1 -1
  164. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js +5 -10
  165. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js.map +1 -1
  166. package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts.map +1 -1
  167. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js +2 -9
  168. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js.map +1 -1
  169. package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts.map +1 -1
  170. package/dist/core/remote-workspace-protocol/lima-owner-directory.js.map +1 -1
  171. package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts.map +1 -1
  172. package/dist/core/remote-workspace-protocol/lima-owner-lock.js.map +1 -1
  173. package/dist/core/remote-workspace-protocol/session.d.ts.map +1 -1
  174. package/dist/core/remote-workspace-protocol/session.js +27 -65
  175. package/dist/core/remote-workspace-protocol/session.js.map +1 -1
  176. package/dist/core/remote-workspace-protocol/shared-transport.d.ts.map +1 -1
  177. package/dist/core/remote-workspace-protocol/shared-transport.js.map +1 -1
  178. package/dist/core/resolve-config-value.d.ts.map +1 -1
  179. package/dist/core/resolve-config-value.js.map +1 -1
  180. package/dist/core/resource-loader.d.ts.map +1 -1
  181. package/dist/core/resource-loader.js +0 -48
  182. package/dist/core/resource-loader.js.map +1 -1
  183. package/dist/core/rules.d.ts.map +1 -1
  184. package/dist/core/rules.js.map +1 -1
  185. package/dist/core/sandbox/command.d.ts.map +1 -1
  186. package/dist/core/sandbox/command.js.map +1 -1
  187. package/dist/core/sandbox/config.d.ts.map +1 -1
  188. package/dist/core/sandbox/config.js.map +1 -1
  189. package/dist/core/sandbox/lima-guest-binary.d.ts.map +1 -1
  190. package/dist/core/sandbox/lima-guest-binary.js.map +1 -1
  191. package/dist/core/sandbox/lima.d.ts +2 -0
  192. package/dist/core/sandbox/lima.d.ts.map +1 -1
  193. package/dist/core/sandbox/lima.js +3 -9
  194. package/dist/core/sandbox/lima.js.map +1 -1
  195. package/dist/core/sandbox/shared-lima-roots.d.ts.map +1 -1
  196. package/dist/core/sandbox/shared-lima-roots.js.map +1 -1
  197. package/dist/core/sandbox/update-shared-guest-binary.d.ts.map +1 -1
  198. package/dist/core/sandbox/update-shared-guest-binary.js.map +1 -1
  199. package/dist/core/session/constants.d.ts.map +1 -1
  200. package/dist/core/session/context-metadata.d.ts.map +1 -1
  201. package/dist/core/session/context-metadata.js.map +1 -1
  202. package/dist/core/session/context.d.ts.map +1 -1
  203. package/dist/core/session/context.js.map +1 -1
  204. package/dist/core/session/ids.d.ts.map +1 -1
  205. package/dist/core/session/ids.js.map +1 -1
  206. package/dist/core/session/in-memory-session-manager.d.ts.map +1 -1
  207. package/dist/core/session/in-memory-session-manager.js +0 -1
  208. package/dist/core/session/in-memory-session-manager.js.map +1 -1
  209. package/dist/core/session/in-memory-session.d.ts.map +1 -1
  210. package/dist/core/session/in-memory-session.js.map +1 -1
  211. package/dist/core/session/jsonl-errors.d.ts.map +1 -1
  212. package/dist/core/session/jsonl-errors.js +0 -11
  213. package/dist/core/session/jsonl-errors.js.map +1 -1
  214. package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
  215. package/dist/core/session/jsonl-helpers.js.map +1 -1
  216. package/dist/core/session/local-session-manager.d.ts.map +1 -1
  217. package/dist/core/session/local-session-manager.js +4 -6
  218. package/dist/core/session/local-session-manager.js.map +1 -1
  219. package/dist/core/session/local-session.d.ts.map +1 -1
  220. package/dist/core/session/local-session.js.map +1 -1
  221. package/dist/core/session/migrations.d.ts.map +1 -1
  222. package/dist/core/session/migrations.js.map +1 -1
  223. package/dist/core/session/remote-session-client.d.ts.map +1 -1
  224. package/dist/core/session/remote-session-client.js +0 -6
  225. package/dist/core/session/remote-session-client.js.map +1 -1
  226. package/dist/core/session/remote-session-manager.d.ts.map +1 -1
  227. package/dist/core/session/remote-session-manager.js +0 -3
  228. package/dist/core/session/remote-session-manager.js.map +1 -1
  229. package/dist/core/session/remote-session.d.ts.map +1 -1
  230. package/dist/core/session/remote-session.js +0 -1
  231. package/dist/core/session/remote-session.js.map +1 -1
  232. package/dist/core/session/session-manager.d.ts.map +1 -1
  233. package/dist/core/session/session.d.ts.map +1 -1
  234. package/dist/core/session/session.js +1 -5
  235. package/dist/core/session/session.js.map +1 -1
  236. package/dist/core/session/stores/in-memory-session-store.d.ts.map +1 -1
  237. package/dist/core/session/stores/in-memory-session-store.js +7 -6
  238. package/dist/core/session/stores/in-memory-session-store.js.map +1 -1
  239. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
  240. package/dist/core/session/stores/jsonl-session-store.js +6 -14
  241. package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
  242. package/dist/core/session/stores/remote-session-store.d.ts.map +1 -1
  243. package/dist/core/session/stores/remote-session-store.js +3 -8
  244. package/dist/core/session/stores/remote-session-store.js.map +1 -1
  245. package/dist/core/session/stores/session-store.d.ts.map +1 -1
  246. package/dist/core/session/types.d.ts.map +1 -1
  247. package/dist/core/session/usage-ledger.d.ts.map +1 -1
  248. package/dist/core/session/usage-ledger.js.map +1 -1
  249. package/dist/core/session-cwd.d.ts.map +1 -1
  250. package/dist/core/session-cwd.js +0 -1
  251. package/dist/core/session-cwd.js.map +1 -1
  252. package/dist/core/settings-manager.d.ts.map +1 -1
  253. package/dist/core/settings-manager.js +9 -17
  254. package/dist/core/settings-manager.js.map +1 -1
  255. package/dist/core/skills.d.ts.map +1 -1
  256. package/dist/core/skills.js +3 -2
  257. package/dist/core/skills.js.map +1 -1
  258. package/dist/core/slash-commands.d.ts.map +1 -1
  259. package/dist/core/source-info.d.ts.map +1 -1
  260. package/dist/core/source-info.js.map +1 -1
  261. package/dist/core/system-prompt.d.ts +1 -1
  262. package/dist/core/system-prompt.d.ts.map +1 -1
  263. package/dist/core/system-prompt.js +3 -2
  264. package/dist/core/system-prompt.js.map +1 -1
  265. package/dist/core/telemetry.d.ts.map +1 -1
  266. package/dist/core/telemetry.js.map +1 -1
  267. package/dist/core/timings.d.ts.map +1 -1
  268. package/dist/core/timings.js.map +1 -1
  269. package/dist/core/tools/bash.d.ts +1 -0
  270. package/dist/core/tools/bash.d.ts.map +1 -1
  271. package/dist/core/tools/bash.js +34 -28
  272. package/dist/core/tools/bash.js.map +1 -1
  273. package/dist/core/tools/compress-context.d.ts.map +1 -1
  274. package/dist/core/tools/compress-context.js.map +1 -1
  275. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  276. package/dist/core/tools/edit-diff.js.map +1 -1
  277. package/dist/core/tools/edit.d.ts.map +1 -1
  278. package/dist/core/tools/edit.js.map +1 -1
  279. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  280. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  281. package/dist/core/tools/find.d.ts.map +1 -1
  282. package/dist/core/tools/find.js.map +1 -1
  283. package/dist/core/tools/grep.d.ts.map +1 -1
  284. package/dist/core/tools/grep.js.map +1 -1
  285. package/dist/core/tools/hash-store.d.ts.map +1 -1
  286. package/dist/core/tools/hash-store.js.map +1 -1
  287. package/dist/core/tools/hashline/apply.d.ts.map +1 -1
  288. package/dist/core/tools/hashline/apply.js.map +1 -1
  289. package/dist/core/tools/hashline/hash.d.ts.map +1 -1
  290. package/dist/core/tools/hashline/hash.js.map +1 -1
  291. package/dist/core/tools/hashline/parse.d.ts.map +1 -1
  292. package/dist/core/tools/hashline/parse.js.map +1 -1
  293. package/dist/core/tools/hashline/resolve.d.ts.map +1 -1
  294. package/dist/core/tools/hashline/resolve.js.map +1 -1
  295. package/dist/core/tools/hashline-utils.d.ts.map +1 -1
  296. package/dist/core/tools/hashline-utils.js.map +1 -1
  297. package/dist/core/tools/index.d.ts.map +1 -1
  298. package/dist/core/tools/index.js.map +1 -1
  299. package/dist/core/tools/ls.d.ts.map +1 -1
  300. package/dist/core/tools/ls.js.map +1 -1
  301. package/dist/core/tools/operations.d.ts +11 -0
  302. package/dist/core/tools/operations.d.ts.map +1 -1
  303. package/dist/core/tools/operations.js +54 -28
  304. package/dist/core/tools/operations.js.map +1 -1
  305. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  306. package/dist/core/tools/output-accumulator.js +12 -18
  307. package/dist/core/tools/output-accumulator.js.map +1 -1
  308. package/dist/core/tools/path-utils.d.ts.map +1 -1
  309. package/dist/core/tools/path-utils.js.map +1 -1
  310. package/dist/core/tools/read.d.ts.map +1 -1
  311. package/dist/core/tools/read.js.map +1 -1
  312. package/dist/core/tools/render-utils.d.ts.map +1 -1
  313. package/dist/core/tools/render-utils.js.map +1 -1
  314. package/dist/core/tools/replace-diff.d.ts.map +1 -1
  315. package/dist/core/tools/replace-diff.js.map +1 -1
  316. package/dist/core/tools/replace-normalize.d.ts.map +1 -1
  317. package/dist/core/tools/replace-normalize.js.map +1 -1
  318. package/dist/core/tools/replace-render.d.ts +1 -1
  319. package/dist/core/tools/replace-render.d.ts.map +1 -1
  320. package/dist/core/tools/replace-render.js.map +1 -1
  321. package/dist/core/tools/runtime.d.ts.map +1 -1
  322. package/dist/core/tools/runtime.js.map +1 -1
  323. package/dist/core/tools/session-history.d.ts.map +1 -1
  324. package/dist/core/tools/session-history.js.map +1 -1
  325. package/dist/core/tools/subagent-agents.d.ts.map +1 -1
  326. package/dist/core/tools/subagent-agents.js.map +1 -1
  327. package/dist/core/tools/subagent.d.ts.map +1 -1
  328. package/dist/core/tools/subagent.js.map +1 -1
  329. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  330. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  331. package/dist/core/tools/truncate.d.ts.map +1 -1
  332. package/dist/core/tools/truncate.js.map +1 -1
  333. package/dist/core/tools/websearch.d.ts.map +1 -1
  334. package/dist/core/tools/websearch.js.map +1 -1
  335. package/dist/core/tools/workspace-tool-host.d.ts +1 -0
  336. package/dist/core/tools/workspace-tool-host.d.ts.map +1 -1
  337. package/dist/core/tools/workspace-tool-host.js +36 -22
  338. package/dist/core/tools/workspace-tool-host.js.map +1 -1
  339. package/dist/core/tools/write.d.ts.map +1 -1
  340. package/dist/core/tools/write.js +0 -1
  341. package/dist/core/tools/write.js.map +1 -1
  342. package/dist/core/workspace-identity.d.ts.map +1 -1
  343. package/dist/daemon/activity-budget.d.ts.map +1 -1
  344. package/dist/daemon/activity-budget.js +2 -3
  345. package/dist/daemon/activity-budget.js.map +1 -1
  346. package/dist/daemon/command.d.ts.map +1 -1
  347. package/dist/daemon/command.js.map +1 -1
  348. package/dist/daemon/config.d.ts +2 -0
  349. package/dist/daemon/config.d.ts.map +1 -1
  350. package/dist/daemon/config.js +4 -0
  351. package/dist/daemon/config.js.map +1 -1
  352. package/dist/daemon/help.d.ts.map +1 -1
  353. package/dist/daemon/help.js +4 -3
  354. package/dist/daemon/help.js.map +1 -1
  355. package/dist/daemon/lsp-config.d.ts.map +1 -1
  356. package/dist/daemon/lsp-config.js.map +1 -1
  357. package/dist/daemon/outbound-budget.d.ts.map +1 -1
  358. package/dist/daemon/outbound-budget.js +2 -4
  359. package/dist/daemon/outbound-budget.js.map +1 -1
  360. package/dist/daemon/security.d.ts.map +1 -1
  361. package/dist/daemon/security.js.map +1 -1
  362. package/dist/daemon/server.d.ts.map +1 -1
  363. package/dist/daemon/server.js.map +1 -1
  364. package/dist/daemon/shared-connection.d.ts.map +1 -1
  365. package/dist/daemon/shared-connection.js +10 -15
  366. package/dist/daemon/shared-connection.js.map +1 -1
  367. package/dist/daemon/shared-revision.d.ts.map +1 -1
  368. package/dist/daemon/shared-revision.js +2 -1
  369. package/dist/daemon/shared-revision.js.map +1 -1
  370. package/dist/daemon/shared-roots.d.ts.map +1 -1
  371. package/dist/daemon/shared-roots.js +0 -1
  372. package/dist/daemon/shared-roots.js.map +1 -1
  373. package/dist/daemon/workspace-runtime.d.ts +2 -0
  374. package/dist/daemon/workspace-runtime.d.ts.map +1 -1
  375. package/dist/daemon/workspace-runtime.js +43 -15
  376. package/dist/daemon/workspace-runtime.js.map +1 -1
  377. package/dist/index.d.ts +1 -1
  378. package/dist/index.d.ts.map +1 -1
  379. package/dist/index.js.map +1 -1
  380. package/dist/main.d.ts.map +1 -1
  381. package/dist/main.js +8 -3
  382. package/dist/main.js.map +1 -1
  383. package/dist/migrations.d.ts.map +1 -1
  384. package/dist/migrations.js.map +1 -1
  385. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  386. package/dist/modes/interactive/components/assistant-message.js +3 -10
  387. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  388. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  389. package/dist/modes/interactive/components/bash-execution.js +4 -9
  390. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  391. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  392. package/dist/modes/interactive/components/bordered-loader.js +0 -3
  393. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  394. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  395. package/dist/modes/interactive/components/branch-summary-message.js +1 -3
  396. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  397. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  398. package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
  399. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  400. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  401. package/dist/modes/interactive/components/config-selector.js +6 -16
  402. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  403. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  404. package/dist/modes/interactive/components/countdown-timer.js +0 -5
  405. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  406. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  407. package/dist/modes/interactive/components/custom-editor.js +1 -8
  408. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  409. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  410. package/dist/modes/interactive/components/custom-message.js +1 -6
  411. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  412. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  413. package/dist/modes/interactive/components/diff.js.map +1 -1
  414. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  415. package/dist/modes/interactive/components/dynamic-border.js +0 -1
  416. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  417. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  418. package/dist/modes/interactive/components/extension-editor.js +1 -7
  419. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  420. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  421. package/dist/modes/interactive/components/extension-input.js +2 -8
  422. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  423. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  424. package/dist/modes/interactive/components/extension-selector.js +1 -9
  425. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  426. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  427. package/dist/modes/interactive/components/footer.js +8 -4
  428. package/dist/modes/interactive/components/footer.js.map +1 -1
  429. package/dist/modes/interactive/components/hook-execution.d.ts.map +1 -1
  430. package/dist/modes/interactive/components/hook-execution.js +2 -5
  431. package/dist/modes/interactive/components/hook-execution.js.map +1 -1
  432. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  433. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  434. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/login-dialog.js +3 -9
  436. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  437. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  439. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  440. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  441. package/dist/modes/interactive/components/message-card.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/message-card.js +0 -1
  443. package/dist/modes/interactive/components/message-card.js.map +1 -1
  444. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  445. package/dist/modes/interactive/components/model-selector.js +13 -28
  446. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  447. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  448. package/dist/modes/interactive/components/oauth-selector.js +3 -12
  449. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  450. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/scoped-models-selector.js +9 -13
  452. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  453. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  454. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  455. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/session-selector.js +33 -58
  457. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  458. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/settings-selector.js +0 -4
  460. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  461. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  462. package/dist/modes/interactive/components/show-images-selector.js +0 -1
  463. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  464. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
  466. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  467. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/theme-selector.js +0 -2
  469. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  470. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/thinking-selector.js +0 -1
  472. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  473. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/tool-execution.js +9 -24
  475. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  476. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  477. package/dist/modes/interactive/components/tree-selector.js +18 -34
  478. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  479. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/user-message-selector.js +3 -6
  481. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  482. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  483. package/dist/modes/interactive/components/user-message.js +0 -4
  484. package/dist/modes/interactive/components/user-message.js.map +1 -1
  485. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  487. package/dist/modes/interactive/interactive-mode.d.ts +13 -0
  488. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  489. package/dist/modes/interactive/interactive-mode.js +162 -136
  490. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  491. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  492. package/dist/modes/interactive/theme/theme.js +0 -7
  493. package/dist/modes/interactive/theme/theme.js.map +1 -1
  494. package/dist/modes/json-event.d.ts.map +1 -1
  495. package/dist/modes/json-event.js.map +1 -1
  496. package/dist/modes/print-mode.d.ts.map +1 -1
  497. package/dist/modes/print-mode.js.map +1 -1
  498. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  499. package/dist/modes/rpc/jsonl.js.map +1 -1
  500. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  501. package/dist/modes/rpc/rpc-client.js +10 -11
  502. package/dist/modes/rpc/rpc-client.js.map +1 -1
  503. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  504. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  505. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  506. package/dist/package-manager-cli.d.ts.map +1 -1
  507. package/dist/package-manager-cli.js +33 -2
  508. package/dist/package-manager-cli.js.map +1 -1
  509. package/dist/utils/ansi.d.ts.map +1 -1
  510. package/dist/utils/ansi.js.map +1 -1
  511. package/dist/utils/binary-self-update.d.ts +25 -0
  512. package/dist/utils/binary-self-update.d.ts.map +1 -0
  513. package/dist/utils/binary-self-update.js +159 -0
  514. package/dist/utils/binary-self-update.js.map +1 -0
  515. package/dist/utils/changelog.d.ts.map +1 -1
  516. package/dist/utils/changelog.js.map +1 -1
  517. package/dist/utils/child-process.d.ts.map +1 -1
  518. package/dist/utils/child-process.js.map +1 -1
  519. package/dist/utils/clipboard-image.d.ts.map +1 -1
  520. package/dist/utils/clipboard-image.js.map +1 -1
  521. package/dist/utils/clipboard-native.d.ts.map +1 -1
  522. package/dist/utils/clipboard-native.js.map +1 -1
  523. package/dist/utils/clipboard.d.ts.map +1 -1
  524. package/dist/utils/clipboard.js.map +1 -1
  525. package/dist/utils/deprecation.d.ts.map +1 -1
  526. package/dist/utils/deprecation.js.map +1 -1
  527. package/dist/utils/directory-completions.d.ts +8 -0
  528. package/dist/utils/directory-completions.d.ts.map +1 -1
  529. package/dist/utils/directory-completions.js +42 -1
  530. package/dist/utils/directory-completions.js.map +1 -1
  531. package/dist/utils/exif-orientation.d.ts.map +1 -1
  532. package/dist/utils/exif-orientation.js.map +1 -1
  533. package/dist/utils/frontmatter.d.ts.map +1 -1
  534. package/dist/utils/frontmatter.js.map +1 -1
  535. package/dist/utils/fs-watch.d.ts.map +1 -1
  536. package/dist/utils/fs-watch.js.map +1 -1
  537. package/dist/utils/git.d.ts.map +1 -1
  538. package/dist/utils/git.js.map +1 -1
  539. package/dist/utils/grip-user-agent.d.ts.map +1 -1
  540. package/dist/utils/grip-user-agent.js.map +1 -1
  541. package/dist/utils/html.d.ts.map +1 -1
  542. package/dist/utils/html.js.map +1 -1
  543. package/dist/utils/image-convert.d.ts.map +1 -1
  544. package/dist/utils/image-convert.js.map +1 -1
  545. package/dist/utils/image-process.d.ts.map +1 -1
  546. package/dist/utils/image-process.js.map +1 -1
  547. package/dist/utils/image-resize-core.d.ts.map +1 -1
  548. package/dist/utils/image-resize-core.js.map +1 -1
  549. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  550. package/dist/utils/image-resize-worker.js.map +1 -1
  551. package/dist/utils/image-resize.d.ts.map +1 -1
  552. package/dist/utils/image-resize.js.map +1 -1
  553. package/dist/utils/json.d.ts.map +1 -1
  554. package/dist/utils/json.js.map +1 -1
  555. package/dist/utils/mime.d.ts.map +1 -1
  556. package/dist/utils/mime.js.map +1 -1
  557. package/dist/utils/open-browser.d.ts.map +1 -1
  558. package/dist/utils/open-browser.js.map +1 -1
  559. package/dist/utils/paths.d.ts.map +1 -1
  560. package/dist/utils/paths.js.map +1 -1
  561. package/dist/utils/photon.d.ts.map +1 -1
  562. package/dist/utils/photon.js +10 -5
  563. package/dist/utils/photon.js.map +1 -1
  564. package/dist/utils/shell.d.ts.map +1 -1
  565. package/dist/utils/shell.js.map +1 -1
  566. package/dist/utils/sleep.d.ts.map +1 -1
  567. package/dist/utils/sleep.js.map +1 -1
  568. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  569. package/dist/utils/syntax-highlight.js +1 -1
  570. package/dist/utils/syntax-highlight.js.map +1 -1
  571. package/dist/utils/tools-manager.d.ts.map +1 -1
  572. package/dist/utils/tools-manager.js.map +1 -1
  573. package/dist/utils/version-check.d.ts.map +1 -1
  574. package/dist/utils/version-check.js.map +1 -1
  575. package/dist/utils/windows-self-update.d.ts.map +1 -1
  576. package/dist/utils/windows-self-update.js.map +1 -1
  577. package/docs/extensions.md +31 -1
  578. package/docs/sandbox.md +6 -0
  579. package/docs/sessions.md +1 -1
  580. package/docs/skills.md +4 -4
  581. package/docs/usage.md +2 -1
  582. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  583. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  584. package/examples/extensions/sandbox/package.json +2 -2
  585. package/examples/extensions/with-deps/package.json +1 -1
  586. package/npm-shrinkwrap.json +602 -834
  587. package/package.json +20 -21
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,mBAAmB,EACnB,mBAAmB,EACnB,SAAS,EAIT,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9D;AAgPD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,CA4B1G","sourcesContent":["import type {\n\tHookAggregateResult,\n\tHookExecutionResult,\n\tHookInput,\n\tHookStructuredOutput,\n\tJsonObject,\n\tJsonValue,\n} from \"./types.ts\";\n\nexport const MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS = 10_000;\n\nexport function capModelVisibleHookField(value: string): string {\n\treturn value.length <= MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS\n\t\t? value\n\t\t: value.slice(0, MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS);\n}\n\nfunction object(value: JsonValue | undefined): JsonObject | undefined {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value) ? value : undefined;\n}\nfunction string(value: JsonValue | undefined): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\nfunction boolean(value: JsonValue | undefined): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\nfunction nonnegativeNumber(value: JsonValue | undefined): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : undefined;\n}\nconst permissionRank = { allow: 0, ask: 1, defer: 2, deny: 3 } as const;\ntype PermissionDecision = keyof typeof permissionRank;\ntype UnsupportedPermissionDecision = \"ask\" | \"defer\";\nfunction permission(value: JsonValue | undefined): PermissionDecision | undefined {\n\treturn value === \"allow\" || value === \"ask\" || value === \"defer\" || value === \"deny\" ? value : undefined;\n}\n\nfunction unsupportedPermissionReason(decision: UnsupportedPermissionDecision): string {\n\treturn decision === \"ask\"\n\t\t? \"Tool execution blocked: hook requested permission, but no permission engine is available\"\n\t\t: \"Tool execution blocked: hook deferred permission, but no permission engine is available\";\n}\nfunction acceptsCommonControl(input: HookInput): boolean {\n\treturn input.hook_event_name !== \"SessionEnd\";\n}\nfunction capped(value: string | undefined): string | undefined {\n\treturn value === undefined ? undefined : capModelVisibleHookField(value);\n}\n\nfunction applyBlockingResult(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\taggregate: HookAggregateResult,\n): PermissionDecision | undefined {\n\tif (!result.blocking) return undefined;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(result.blockingReason);\n\treturn input.hook_event_name === \"PreToolUse\" ? \"deny\" : undefined;\n}\n\nfunction appendPlainTextOutput(\n\tinput: HookInput,\n\ttext: string,\n\tmalformedJson: boolean,\n\taggregate: HookAggregateResult,\n): void {\n\tif (malformedJson) return;\n\tif (input.hook_event_name !== \"SessionStart\" && input.hook_event_name !== \"UserPromptSubmit\") return;\n\tconst visibleText = capModelVisibleHookField(text);\n\taggregate.plainText.push(visibleText);\n\taggregate.additionalContext.push(visibleText);\n}\n\nfunction applyCommonJsonOutput(input: HookInput, output: HookStructuredOutput, aggregate: HookAggregateResult): void {\n\tif (acceptsCommonControl(input) && output.continue === false) {\n\t\taggregate.continue = false;\n\t\taggregate.reason ??= capped(output.stopReason);\n\t}\n\tif (typeof output.systemMessage === \"string\") aggregate.systemMessages.push(output.systemMessage);\n}\n\nfunction resolveSpecificOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n): JsonObject | undefined {\n\tconst specific = object(output.hookSpecificOutput);\n\tif (!specific || specific.hookEventName === input.hook_event_name) return specific;\n\tresult.diagnostic ??= {\n\t\tlevel: \"warning\",\n\t\tcode: \"malformed-output\",\n\t\tmessage: `hookSpecificOutput.hookEventName must match ${input.hook_event_name}; fields were ignored`,\n\t\tsource: result.hook.source,\n\t\tevent: input.hook_event_name,\n\t};\n\treturn undefined;\n}\n\nfunction acceptsAdditionalContext(input: HookInput): boolean {\n\tswitch (input.hook_event_name) {\n\t\tcase \"StopFailure\":\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\tcase \"SessionEnd\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getAdditionalContext(input: HookInput, specific: JsonObject | undefined): string | undefined {\n\tconst context = capped(string(specific?.additionalContext));\n\treturn context !== undefined && acceptsAdditionalContext(input) ? context : undefined;\n}\n\nfunction applyDecisionBlock(output: HookStructuredOutput, aggregate: HookAggregateResult): void {\n\tif (output.decision !== \"block\") return;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(output.reason);\n}\n\nfunction applySessionStartOutput(specific: JsonObject | undefined, aggregate: HookAggregateResult): void {\n\taggregate.sessionTitle = string(specific?.sessionTitle) ?? aggregate.sessionTitle;\n\taggregate.initialUserMessage = capped(string(specific?.initialUserMessage)) ?? aggregate.initialUserMessage;\n\taggregate.reloadSkills = boolean(specific?.reloadSkills) ?? aggregate.reloadSkills;\n}\n\nfunction applyUserPromptSubmitOutput(\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\taggregate.sessionTitle = string(specific?.sessionTitle) ?? aggregate.sessionTitle;\n\tapplyDecisionBlock(output, aggregate);\n}\n\nfunction selectMoreRestrictivePermission(\n\tcurrent: PermissionDecision | undefined,\n\tnext: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tif (next === undefined) return current;\n\tif (current === undefined || permissionRank[next] > permissionRank[current]) return next;\n\treturn current;\n}\n\nfunction applyPreToolUseOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n\tbestPermission: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tconst next = permission(specific?.permissionDecision);\n\tconst selectedPermission = selectMoreRestrictivePermission(bestPermission, next);\n\tif (next === \"ask\" || next === \"defer\") {\n\t\tresult.diagnostic ??= {\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"policy\",\n\t\t\tmessage: `${unsupportedPermissionReason(next)} (permissionDecision: ${next})`,\n\t\t\tsource: result.hook.source,\n\t\t\tevent: input.hook_event_name,\n\t\t};\n\t}\n\tconst updated = object(specific?.updatedInput);\n\tif (updated !== undefined) aggregate.updatedInput = updated;\n\tif (next === \"deny\") {\n\t\taggregate.blocked = true;\n\t\taggregate.reason ??= capped(string(specific?.permissionDecisionReason));\n\t}\n\treturn selectedPermission;\n}\n\nfunction applyPostToolUseOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\tapplyDecisionBlock(output, aggregate);\n\tif (specific?.updatedToolOutput !== undefined) {\n\t\taggregate.updatedToolOutput = specific.updatedToolOutput;\n\t\treturn;\n\t}\n\tif (specific?.updatedMCPToolOutput === undefined) return;\n\tif (input.hook_event_name === \"PostToolUse\" && input.tool_name.startsWith(\"mcp__\")) {\n\t\taggregate.updatedToolOutput = specific.updatedMCPToolOutput;\n\t\treturn;\n\t}\n\tresult.diagnostic ??= {\n\t\tlevel: \"warning\",\n\t\tcode: \"unsupported-update\",\n\t\tmessage: \"updatedMCPToolOutput is only supported for mcp__ tools; original output was retained\",\n\t\tsource: result.hook.source,\n\t\tevent: input.hook_event_name,\n\t};\n}\n\nfunction applyStopOutput(\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\tcontext: string | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\tif (output.decision !== \"block\" && context === undefined) return;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(output.reason) ?? context;\n\tconst progress = nonnegativeNumber(specific?.continuationProgress);\n\tif (progress !== undefined) {\n\t\taggregate.stopContinuationProgress = (aggregate.stopContinuationProgress ?? 0) + progress;\n\t}\n}\n\nfunction applyEventSpecificOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\tcontext: string | undefined,\n\taggregate: HookAggregateResult,\n\tbestPermission: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tswitch (input.hook_event_name) {\n\t\tcase \"SessionStart\":\n\t\t\tapplySessionStartOutput(specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"UserPromptSubmit\":\n\t\t\tapplyUserPromptSubmitOutput(output, specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"PreToolUse\":\n\t\t\treturn applyPreToolUseOutput(input, result, specific, aggregate, bestPermission);\n\t\tcase \"PostToolUse\":\n\t\t\tapplyPostToolUseOutput(input, result, output, specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"PostToolUseFailure\":\n\t\tcase \"PreCompact\":\n\t\t\tapplyDecisionBlock(output, aggregate);\n\t\t\tbreak;\n\t\tcase \"Stop\":\n\t\t\tapplyStopOutput(output, specific, context, aggregate);\n\t\t\tbreak;\n\t\tcase \"StopFailure\":\n\t\tcase \"PostCompact\":\n\t\tcase \"SessionEnd\":\n\t\t\tbreak;\n\t}\n\treturn bestPermission;\n}\n\nfunction finalizePermission(aggregate: HookAggregateResult, bestPermission: PermissionDecision | undefined): void {\n\taggregate.permissionDecision = bestPermission;\n\tif (bestPermission !== \"ask\" && bestPermission !== \"defer\") return;\n\taggregate.blocked = true;\n\taggregate.reason = unsupportedPermissionReason(bestPermission);\n}\n\nexport function aggregateHookResults(input: HookInput, results: HookExecutionResult[]): HookAggregateResult {\n\tconst aggregate: HookAggregateResult = {\n\t\tcontinue: true,\n\t\tblocked: false,\n\t\tadditionalContext: [],\n\t\tsystemMessages: [],\n\t\tplainText: [],\n\t\tresults,\n\t};\n\tlet bestPermission: PermissionDecision | undefined;\n\tfor (const result of results.sort((left, right) => left.hook.order - right.hook.order)) {\n\t\tif (result.status !== \"completed\") continue;\n\t\tbestPermission = selectMoreRestrictivePermission(bestPermission, applyBlockingResult(input, result, aggregate));\n\t\tif (result.exitCode !== 0) continue;\n\t\tif (result.output.kind === \"text\") {\n\t\t\tappendPlainTextOutput(input, result.output.text, result.output.malformedJson, aggregate);\n\t\t\tcontinue;\n\t\t}\n\t\tif (result.output.kind !== \"json\") continue;\n\t\tconst output = result.output.value;\n\t\tapplyCommonJsonOutput(input, output, aggregate);\n\t\tconst specific = resolveSpecificOutput(input, result, output);\n\t\tconst context = getAdditionalContext(input, specific);\n\t\tif (context !== undefined) aggregate.additionalContext.push(context);\n\t\tbestPermission = applyEventSpecificOutput(input, result, output, specific, context, aggregate, bestPermission);\n\t}\n\tfinalizePermission(aggregate, bestPermission);\n\treturn aggregate;\n}\n"]}
1
+ {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,mBAAmB,EACnB,mBAAmB,EACnB,SAAS,EAIT,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9D;AAgPD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,CA4B1G"}
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../src/core/hooks/aggregate.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tHookAggregateResult,\n\tHookExecutionResult,\n\tHookInput,\n\tHookStructuredOutput,\n\tJsonObject,\n\tJsonValue,\n} from \"./types.ts\";\n\nexport const MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS = 10_000;\n\nexport function capModelVisibleHookField(value: string): string {\n\treturn value.length <= MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS\n\t\t? value\n\t\t: value.slice(0, MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS);\n}\n\nfunction object(value: JsonValue | undefined): JsonObject | undefined {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value) ? value : undefined;\n}\nfunction string(value: JsonValue | undefined): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\nfunction boolean(value: JsonValue | undefined): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\nfunction nonnegativeNumber(value: JsonValue | undefined): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : undefined;\n}\nconst permissionRank = { allow: 0, ask: 1, defer: 2, deny: 3 } as const;\ntype PermissionDecision = keyof typeof permissionRank;\ntype UnsupportedPermissionDecision = \"ask\" | \"defer\";\nfunction permission(value: JsonValue | undefined): PermissionDecision | undefined {\n\treturn value === \"allow\" || value === \"ask\" || value === \"defer\" || value === \"deny\" ? value : undefined;\n}\n\nfunction unsupportedPermissionReason(decision: UnsupportedPermissionDecision): string {\n\treturn decision === \"ask\"\n\t\t? \"Tool execution blocked: hook requested permission, but no permission engine is available\"\n\t\t: \"Tool execution blocked: hook deferred permission, but no permission engine is available\";\n}\nfunction acceptsCommonControl(input: HookInput): boolean {\n\treturn input.hook_event_name !== \"SessionEnd\";\n}\nfunction capped(value: string | undefined): string | undefined {\n\treturn value === undefined ? undefined : capModelVisibleHookField(value);\n}\n\nfunction applyBlockingResult(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\taggregate: HookAggregateResult,\n): PermissionDecision | undefined {\n\tif (!result.blocking) return undefined;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(result.blockingReason);\n\treturn input.hook_event_name === \"PreToolUse\" ? \"deny\" : undefined;\n}\n\nfunction appendPlainTextOutput(\n\tinput: HookInput,\n\ttext: string,\n\tmalformedJson: boolean,\n\taggregate: HookAggregateResult,\n): void {\n\tif (malformedJson) return;\n\tif (input.hook_event_name !== \"SessionStart\" && input.hook_event_name !== \"UserPromptSubmit\") return;\n\tconst visibleText = capModelVisibleHookField(text);\n\taggregate.plainText.push(visibleText);\n\taggregate.additionalContext.push(visibleText);\n}\n\nfunction applyCommonJsonOutput(input: HookInput, output: HookStructuredOutput, aggregate: HookAggregateResult): void {\n\tif (acceptsCommonControl(input) && output.continue === false) {\n\t\taggregate.continue = false;\n\t\taggregate.reason ??= capped(output.stopReason);\n\t}\n\tif (typeof output.systemMessage === \"string\") aggregate.systemMessages.push(output.systemMessage);\n}\n\nfunction resolveSpecificOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n): JsonObject | undefined {\n\tconst specific = object(output.hookSpecificOutput);\n\tif (!specific || specific.hookEventName === input.hook_event_name) return specific;\n\tresult.diagnostic ??= {\n\t\tlevel: \"warning\",\n\t\tcode: \"malformed-output\",\n\t\tmessage: `hookSpecificOutput.hookEventName must match ${input.hook_event_name}; fields were ignored`,\n\t\tsource: result.hook.source,\n\t\tevent: input.hook_event_name,\n\t};\n\treturn undefined;\n}\n\nfunction acceptsAdditionalContext(input: HookInput): boolean {\n\tswitch (input.hook_event_name) {\n\t\tcase \"StopFailure\":\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\tcase \"SessionEnd\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getAdditionalContext(input: HookInput, specific: JsonObject | undefined): string | undefined {\n\tconst context = capped(string(specific?.additionalContext));\n\treturn context !== undefined && acceptsAdditionalContext(input) ? context : undefined;\n}\n\nfunction applyDecisionBlock(output: HookStructuredOutput, aggregate: HookAggregateResult): void {\n\tif (output.decision !== \"block\") return;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(output.reason);\n}\n\nfunction applySessionStartOutput(specific: JsonObject | undefined, aggregate: HookAggregateResult): void {\n\taggregate.sessionTitle = string(specific?.sessionTitle) ?? aggregate.sessionTitle;\n\taggregate.initialUserMessage = capped(string(specific?.initialUserMessage)) ?? aggregate.initialUserMessage;\n\taggregate.reloadSkills = boolean(specific?.reloadSkills) ?? aggregate.reloadSkills;\n}\n\nfunction applyUserPromptSubmitOutput(\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\taggregate.sessionTitle = string(specific?.sessionTitle) ?? aggregate.sessionTitle;\n\tapplyDecisionBlock(output, aggregate);\n}\n\nfunction selectMoreRestrictivePermission(\n\tcurrent: PermissionDecision | undefined,\n\tnext: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tif (next === undefined) return current;\n\tif (current === undefined || permissionRank[next] > permissionRank[current]) return next;\n\treturn current;\n}\n\nfunction applyPreToolUseOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n\tbestPermission: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tconst next = permission(specific?.permissionDecision);\n\tconst selectedPermission = selectMoreRestrictivePermission(bestPermission, next);\n\tif (next === \"ask\" || next === \"defer\") {\n\t\tresult.diagnostic ??= {\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"policy\",\n\t\t\tmessage: `${unsupportedPermissionReason(next)} (permissionDecision: ${next})`,\n\t\t\tsource: result.hook.source,\n\t\t\tevent: input.hook_event_name,\n\t\t};\n\t}\n\tconst updated = object(specific?.updatedInput);\n\tif (updated !== undefined) aggregate.updatedInput = updated;\n\tif (next === \"deny\") {\n\t\taggregate.blocked = true;\n\t\taggregate.reason ??= capped(string(specific?.permissionDecisionReason));\n\t}\n\treturn selectedPermission;\n}\n\nfunction applyPostToolUseOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\tapplyDecisionBlock(output, aggregate);\n\tif (specific?.updatedToolOutput !== undefined) {\n\t\taggregate.updatedToolOutput = specific.updatedToolOutput;\n\t\treturn;\n\t}\n\tif (specific?.updatedMCPToolOutput === undefined) return;\n\tif (input.hook_event_name === \"PostToolUse\" && input.tool_name.startsWith(\"mcp__\")) {\n\t\taggregate.updatedToolOutput = specific.updatedMCPToolOutput;\n\t\treturn;\n\t}\n\tresult.diagnostic ??= {\n\t\tlevel: \"warning\",\n\t\tcode: \"unsupported-update\",\n\t\tmessage: \"updatedMCPToolOutput is only supported for mcp__ tools; original output was retained\",\n\t\tsource: result.hook.source,\n\t\tevent: input.hook_event_name,\n\t};\n}\n\nfunction applyStopOutput(\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\tcontext: string | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\tif (output.decision !== \"block\" && context === undefined) return;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(output.reason) ?? context;\n\tconst progress = nonnegativeNumber(specific?.continuationProgress);\n\tif (progress !== undefined) {\n\t\taggregate.stopContinuationProgress = (aggregate.stopContinuationProgress ?? 0) + progress;\n\t}\n}\n\nfunction applyEventSpecificOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\tcontext: string | undefined,\n\taggregate: HookAggregateResult,\n\tbestPermission: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tswitch (input.hook_event_name) {\n\t\tcase \"SessionStart\":\n\t\t\tapplySessionStartOutput(specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"UserPromptSubmit\":\n\t\t\tapplyUserPromptSubmitOutput(output, specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"PreToolUse\":\n\t\t\treturn applyPreToolUseOutput(input, result, specific, aggregate, bestPermission);\n\t\tcase \"PostToolUse\":\n\t\t\tapplyPostToolUseOutput(input, result, output, specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"PostToolUseFailure\":\n\t\tcase \"PreCompact\":\n\t\t\tapplyDecisionBlock(output, aggregate);\n\t\t\tbreak;\n\t\tcase \"Stop\":\n\t\t\tapplyStopOutput(output, specific, context, aggregate);\n\t\t\tbreak;\n\t\tcase \"StopFailure\":\n\t\tcase \"PostCompact\":\n\t\tcase \"SessionEnd\":\n\t\t\tbreak;\n\t}\n\treturn bestPermission;\n}\n\nfunction finalizePermission(aggregate: HookAggregateResult, bestPermission: PermissionDecision | undefined): void {\n\taggregate.permissionDecision = bestPermission;\n\tif (bestPermission !== \"ask\" && bestPermission !== \"defer\") return;\n\taggregate.blocked = true;\n\taggregate.reason = unsupportedPermissionReason(bestPermission);\n}\n\nexport function aggregateHookResults(input: HookInput, results: HookExecutionResult[]): HookAggregateResult {\n\tconst aggregate: HookAggregateResult = {\n\t\tcontinue: true,\n\t\tblocked: false,\n\t\tadditionalContext: [],\n\t\tsystemMessages: [],\n\t\tplainText: [],\n\t\tresults,\n\t};\n\tlet bestPermission: PermissionDecision | undefined;\n\tfor (const result of results.sort((left, right) => left.hook.order - right.hook.order)) {\n\t\tif (result.status !== \"completed\") continue;\n\t\tbestPermission = selectMoreRestrictivePermission(bestPermission, applyBlockingResult(input, result, aggregate));\n\t\tif (result.exitCode !== 0) continue;\n\t\tif (result.output.kind === \"text\") {\n\t\t\tappendPlainTextOutput(input, result.output.text, result.output.malformedJson, aggregate);\n\t\t\tcontinue;\n\t\t}\n\t\tif (result.output.kind !== \"json\") continue;\n\t\tconst output = result.output.value;\n\t\tapplyCommonJsonOutput(input, output, aggregate);\n\t\tconst specific = resolveSpecificOutput(input, result, output);\n\t\tconst context = getAdditionalContext(input, specific);\n\t\tif (context !== undefined) aggregate.additionalContext.push(context);\n\t\tbestPermission = applyEventSpecificOutput(input, result, output, specific, context, aggregate, bestPermission);\n\t}\n\tfinalizePermission(aggregate, bestPermission);\n\treturn aggregate;\n}\n"]}
1
+ {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../src/core/hooks/aggregate.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,kCAAkC,GAAG,MAAM,CAAC;AAEzD,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACrD,OAAO,KAAK,CAAC,MAAM,IAAI,kCAAkC;QACxD,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,kCAAkC,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,MAAM,CAAC,KAA4B;IAC3C,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACjG,CAAC;AACD,SAAS,MAAM,CAAC,KAA4B;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AACD,SAAS,OAAO,CAAC,KAA4B;IAC5C,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AACD,SAAS,iBAAiB,CAAC,KAA4B;IACtD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9F,CAAC;AACD,MAAM,cAAc,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAGxE,SAAS,UAAU,CAAC,KAA4B;IAC/C,OAAO,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1G,CAAC;AAED,SAAS,2BAA2B,CAAC,QAAuC;IAC3E,OAAO,QAAQ,KAAK,KAAK;QACxB,CAAC,CAAC,0FAA0F;QAC5F,CAAC,CAAC,yFAAyF,CAAC;AAC9F,CAAC;AACD,SAAS,oBAAoB,CAAC,KAAgB;IAC7C,OAAO,KAAK,CAAC,eAAe,KAAK,YAAY,CAAC;AAC/C,CAAC;AACD,SAAS,MAAM,CAAC,KAAyB;IACxC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,mBAAmB,CAC3B,KAAgB,EAChB,MAA2B,EAC3B,SAA8B;IAE9B,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IACvC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,eAAe,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED,SAAS,qBAAqB,CAC7B,KAAgB,EAChB,IAAY,EACZ,aAAsB,EACtB,SAA8B;IAE9B,IAAI,aAAa;QAAE,OAAO;IAC1B,IAAI,KAAK,CAAC,eAAe,KAAK,cAAc,IAAI,KAAK,CAAC,eAAe,KAAK,kBAAkB;QAAE,OAAO;IACrG,MAAM,WAAW,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;IACnD,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAgB,EAAE,MAA4B,EAAE,SAA8B;IAC5G,IAAI,oBAAoB,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC9D,SAAS,CAAC,QAAQ,GAAG,KAAK,CAAC;QAC3B,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ;QAAE,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AACnG,CAAC;AAED,SAAS,qBAAqB,CAC7B,KAAgB,EAChB,MAA2B,EAC3B,MAA4B;IAE5B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,aAAa,KAAK,KAAK,CAAC,eAAe;QAAE,OAAO,QAAQ,CAAC;IACnF,MAAM,CAAC,UAAU,KAAK;QACrB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,+CAA+C,KAAK,CAAC,eAAe,uBAAuB;QACpG,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;QAC1B,KAAK,EAAE,KAAK,CAAC,eAAe;KAC5B,CAAC;IACF,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAgB;IACjD,QAAQ,KAAK,CAAC,eAAe,EAAE,CAAC;QAC/B,KAAK,aAAa,CAAC;QACnB,KAAK,YAAY,CAAC;QAClB,KAAK,aAAa,CAAC;QACnB,KAAK,YAAY;YAChB,OAAO,KAAK,CAAC;QACd;YACC,OAAO,IAAI,CAAC;IACd,CAAC;AACF,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAgB,EAAE,QAAgC;IAC/E,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC5D,OAAO,OAAO,KAAK,SAAS,IAAI,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACvF,CAAC;AAED,SAAS,kBAAkB,CAAC,MAA4B,EAAE,SAA8B;IACvF,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO;IACxC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAgC,EAAE,SAA8B;IAChG,SAAS,CAAC,YAAY,GAAG,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,SAAS,CAAC,YAAY,CAAC;IAClF,SAAS,CAAC,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC,IAAI,SAAS,CAAC,kBAAkB,CAAC;IAC5G,SAAS,CAAC,YAAY,GAAG,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,SAAS,CAAC,YAAY,CAAC;AACpF,CAAC;AAED,SAAS,2BAA2B,CACnC,MAA4B,EAC5B,QAAgC,EAChC,SAA8B;IAE9B,SAAS,CAAC,YAAY,GAAG,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,SAAS,CAAC,YAAY,CAAC;IAClF,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,+BAA+B,CACvC,OAAuC,EACvC,IAAoC;IAEpC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACvC,IAAI,OAAO,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACzF,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAC7B,KAAgB,EAChB,MAA2B,EAC3B,QAAgC,EAChC,SAA8B,EAC9B,cAA8C;IAE9C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACtD,MAAM,kBAAkB,GAAG,+BAA+B,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACjF,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACxC,MAAM,CAAC,UAAU,KAAK;YACrB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,GAAG,2BAA2B,CAAC,IAAI,CAAC,yBAAyB,IAAI,GAAG;YAC7E,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;YAC1B,KAAK,EAAE,KAAK,CAAC,eAAe;SAC5B,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS;QAAE,SAAS,CAAC,YAAY,GAAG,OAAO,CAAC;IAC5D,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACrB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QACzB,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,kBAAkB,CAAC;AAC3B,CAAC;AAED,SAAS,sBAAsB,CAC9B,KAAgB,EAChB,MAA2B,EAC3B,MAA4B,EAC5B,QAAgC,EAChC,SAA8B;IAE9B,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC,IAAI,QAAQ,EAAE,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC/C,SAAS,CAAC,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC;QACzD,OAAO;IACR,CAAC;IACD,IAAI,QAAQ,EAAE,oBAAoB,KAAK,SAAS;QAAE,OAAO;IACzD,IAAI,KAAK,CAAC,eAAe,KAAK,aAAa,IAAI,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACpF,SAAS,CAAC,iBAAiB,GAAG,QAAQ,CAAC,oBAAoB,CAAC;QAC5D,OAAO;IACR,CAAC;IACD,MAAM,CAAC,UAAU,KAAK;QACrB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,sFAAsF;QAC/F,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;QAC1B,KAAK,EAAE,KAAK,CAAC,eAAe;KAC5B,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CACvB,MAA4B,EAC5B,QAAgC,EAChC,OAA2B,EAC3B,SAA8B;IAE9B,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO;IACjE,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC;IACtD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IACnE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,SAAS,CAAC,wBAAwB,GAAG,CAAC,SAAS,CAAC,wBAAwB,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC3F,CAAC;AACF,CAAC;AAED,SAAS,wBAAwB,CAChC,KAAgB,EAChB,MAA2B,EAC3B,MAA4B,EAC5B,QAAgC,EAChC,OAA2B,EAC3B,SAA8B,EAC9B,cAA8C;IAE9C,QAAQ,KAAK,CAAC,eAAe,EAAE,CAAC;QAC/B,KAAK,cAAc;YAClB,uBAAuB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC7C,MAAM;QACP,KAAK,kBAAkB;YACtB,2BAA2B,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YACzD,MAAM;QACP,KAAK,YAAY;YAChB,OAAO,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;QAClF,KAAK,aAAa;YACjB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YACnE,MAAM;QACP,KAAK,oBAAoB,CAAC;QAC1B,KAAK,YAAY;YAChB,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACtC,MAAM;QACP,KAAK,MAAM;YACV,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACtD,MAAM;QACP,KAAK,aAAa,CAAC;QACnB,KAAK,aAAa,CAAC;QACnB,KAAK,YAAY;YAChB,MAAM;IACR,CAAC;IACD,OAAO,cAAc,CAAC;AACvB,CAAC;AAED,SAAS,kBAAkB,CAAC,SAA8B,EAAE,cAA8C;IACzG,SAAS,CAAC,kBAAkB,GAAG,cAAc,CAAC;IAC9C,IAAI,cAAc,KAAK,KAAK,IAAI,cAAc,KAAK,OAAO;QAAE,OAAO;IACnE,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,MAAM,GAAG,2BAA2B,CAAC,cAAc,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAgB,EAAE,OAA8B;IACpF,MAAM,SAAS,GAAwB;QACtC,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,KAAK;QACd,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,EAAE;QAClB,SAAS,EAAE,EAAE;QACb,OAAO;KACP,CAAC;IACF,IAAI,cAA8C,CAAC;IACnD,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACxF,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;YAAE,SAAS;QAC5C,cAAc,GAAG,+BAA+B,CAAC,cAAc,EAAE,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;QAChH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;YAAE,SAAS;QACpC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACnC,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;YACzF,SAAS;QACV,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QACnC,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtD,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrE,cAAc,GAAG,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAChH,CAAC;IACD,kBAAkB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAC9C,OAAO,SAAS,CAAC;AAClB,CAAC","sourcesContent":["import type {\n\tHookAggregateResult,\n\tHookExecutionResult,\n\tHookInput,\n\tHookStructuredOutput,\n\tJsonObject,\n\tJsonValue,\n} from \"./types.ts\";\n\nexport const MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS = 10_000;\n\nexport function capModelVisibleHookField(value: string): string {\n\treturn value.length <= MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS\n\t\t? value\n\t\t: value.slice(0, MAX_MODEL_VISIBLE_HOOK_FIELD_CHARS);\n}\n\nfunction object(value: JsonValue | undefined): JsonObject | undefined {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value) ? value : undefined;\n}\nfunction string(value: JsonValue | undefined): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\nfunction boolean(value: JsonValue | undefined): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\nfunction nonnegativeNumber(value: JsonValue | undefined): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? value : undefined;\n}\nconst permissionRank = { allow: 0, ask: 1, defer: 2, deny: 3 } as const;\ntype PermissionDecision = keyof typeof permissionRank;\ntype UnsupportedPermissionDecision = \"ask\" | \"defer\";\nfunction permission(value: JsonValue | undefined): PermissionDecision | undefined {\n\treturn value === \"allow\" || value === \"ask\" || value === \"defer\" || value === \"deny\" ? value : undefined;\n}\n\nfunction unsupportedPermissionReason(decision: UnsupportedPermissionDecision): string {\n\treturn decision === \"ask\"\n\t\t? \"Tool execution blocked: hook requested permission, but no permission engine is available\"\n\t\t: \"Tool execution blocked: hook deferred permission, but no permission engine is available\";\n}\nfunction acceptsCommonControl(input: HookInput): boolean {\n\treturn input.hook_event_name !== \"SessionEnd\";\n}\nfunction capped(value: string | undefined): string | undefined {\n\treturn value === undefined ? undefined : capModelVisibleHookField(value);\n}\n\nfunction applyBlockingResult(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\taggregate: HookAggregateResult,\n): PermissionDecision | undefined {\n\tif (!result.blocking) return undefined;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(result.blockingReason);\n\treturn input.hook_event_name === \"PreToolUse\" ? \"deny\" : undefined;\n}\n\nfunction appendPlainTextOutput(\n\tinput: HookInput,\n\ttext: string,\n\tmalformedJson: boolean,\n\taggregate: HookAggregateResult,\n): void {\n\tif (malformedJson) return;\n\tif (input.hook_event_name !== \"SessionStart\" && input.hook_event_name !== \"UserPromptSubmit\") return;\n\tconst visibleText = capModelVisibleHookField(text);\n\taggregate.plainText.push(visibleText);\n\taggregate.additionalContext.push(visibleText);\n}\n\nfunction applyCommonJsonOutput(input: HookInput, output: HookStructuredOutput, aggregate: HookAggregateResult): void {\n\tif (acceptsCommonControl(input) && output.continue === false) {\n\t\taggregate.continue = false;\n\t\taggregate.reason ??= capped(output.stopReason);\n\t}\n\tif (typeof output.systemMessage === \"string\") aggregate.systemMessages.push(output.systemMessage);\n}\n\nfunction resolveSpecificOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n): JsonObject | undefined {\n\tconst specific = object(output.hookSpecificOutput);\n\tif (!specific || specific.hookEventName === input.hook_event_name) return specific;\n\tresult.diagnostic ??= {\n\t\tlevel: \"warning\",\n\t\tcode: \"malformed-output\",\n\t\tmessage: `hookSpecificOutput.hookEventName must match ${input.hook_event_name}; fields were ignored`,\n\t\tsource: result.hook.source,\n\t\tevent: input.hook_event_name,\n\t};\n\treturn undefined;\n}\n\nfunction acceptsAdditionalContext(input: HookInput): boolean {\n\tswitch (input.hook_event_name) {\n\t\tcase \"StopFailure\":\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\tcase \"SessionEnd\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getAdditionalContext(input: HookInput, specific: JsonObject | undefined): string | undefined {\n\tconst context = capped(string(specific?.additionalContext));\n\treturn context !== undefined && acceptsAdditionalContext(input) ? context : undefined;\n}\n\nfunction applyDecisionBlock(output: HookStructuredOutput, aggregate: HookAggregateResult): void {\n\tif (output.decision !== \"block\") return;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(output.reason);\n}\n\nfunction applySessionStartOutput(specific: JsonObject | undefined, aggregate: HookAggregateResult): void {\n\taggregate.sessionTitle = string(specific?.sessionTitle) ?? aggregate.sessionTitle;\n\taggregate.initialUserMessage = capped(string(specific?.initialUserMessage)) ?? aggregate.initialUserMessage;\n\taggregate.reloadSkills = boolean(specific?.reloadSkills) ?? aggregate.reloadSkills;\n}\n\nfunction applyUserPromptSubmitOutput(\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\taggregate.sessionTitle = string(specific?.sessionTitle) ?? aggregate.sessionTitle;\n\tapplyDecisionBlock(output, aggregate);\n}\n\nfunction selectMoreRestrictivePermission(\n\tcurrent: PermissionDecision | undefined,\n\tnext: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tif (next === undefined) return current;\n\tif (current === undefined || permissionRank[next] > permissionRank[current]) return next;\n\treturn current;\n}\n\nfunction applyPreToolUseOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n\tbestPermission: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tconst next = permission(specific?.permissionDecision);\n\tconst selectedPermission = selectMoreRestrictivePermission(bestPermission, next);\n\tif (next === \"ask\" || next === \"defer\") {\n\t\tresult.diagnostic ??= {\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"policy\",\n\t\t\tmessage: `${unsupportedPermissionReason(next)} (permissionDecision: ${next})`,\n\t\t\tsource: result.hook.source,\n\t\t\tevent: input.hook_event_name,\n\t\t};\n\t}\n\tconst updated = object(specific?.updatedInput);\n\tif (updated !== undefined) aggregate.updatedInput = updated;\n\tif (next === \"deny\") {\n\t\taggregate.blocked = true;\n\t\taggregate.reason ??= capped(string(specific?.permissionDecisionReason));\n\t}\n\treturn selectedPermission;\n}\n\nfunction applyPostToolUseOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\tapplyDecisionBlock(output, aggregate);\n\tif (specific?.updatedToolOutput !== undefined) {\n\t\taggregate.updatedToolOutput = specific.updatedToolOutput;\n\t\treturn;\n\t}\n\tif (specific?.updatedMCPToolOutput === undefined) return;\n\tif (input.hook_event_name === \"PostToolUse\" && input.tool_name.startsWith(\"mcp__\")) {\n\t\taggregate.updatedToolOutput = specific.updatedMCPToolOutput;\n\t\treturn;\n\t}\n\tresult.diagnostic ??= {\n\t\tlevel: \"warning\",\n\t\tcode: \"unsupported-update\",\n\t\tmessage: \"updatedMCPToolOutput is only supported for mcp__ tools; original output was retained\",\n\t\tsource: result.hook.source,\n\t\tevent: input.hook_event_name,\n\t};\n}\n\nfunction applyStopOutput(\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\tcontext: string | undefined,\n\taggregate: HookAggregateResult,\n): void {\n\tif (output.decision !== \"block\" && context === undefined) return;\n\taggregate.blocked = true;\n\taggregate.reason ??= capped(output.reason) ?? context;\n\tconst progress = nonnegativeNumber(specific?.continuationProgress);\n\tif (progress !== undefined) {\n\t\taggregate.stopContinuationProgress = (aggregate.stopContinuationProgress ?? 0) + progress;\n\t}\n}\n\nfunction applyEventSpecificOutput(\n\tinput: HookInput,\n\tresult: HookExecutionResult,\n\toutput: HookStructuredOutput,\n\tspecific: JsonObject | undefined,\n\tcontext: string | undefined,\n\taggregate: HookAggregateResult,\n\tbestPermission: PermissionDecision | undefined,\n): PermissionDecision | undefined {\n\tswitch (input.hook_event_name) {\n\t\tcase \"SessionStart\":\n\t\t\tapplySessionStartOutput(specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"UserPromptSubmit\":\n\t\t\tapplyUserPromptSubmitOutput(output, specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"PreToolUse\":\n\t\t\treturn applyPreToolUseOutput(input, result, specific, aggregate, bestPermission);\n\t\tcase \"PostToolUse\":\n\t\t\tapplyPostToolUseOutput(input, result, output, specific, aggregate);\n\t\t\tbreak;\n\t\tcase \"PostToolUseFailure\":\n\t\tcase \"PreCompact\":\n\t\t\tapplyDecisionBlock(output, aggregate);\n\t\t\tbreak;\n\t\tcase \"Stop\":\n\t\t\tapplyStopOutput(output, specific, context, aggregate);\n\t\t\tbreak;\n\t\tcase \"StopFailure\":\n\t\tcase \"PostCompact\":\n\t\tcase \"SessionEnd\":\n\t\t\tbreak;\n\t}\n\treturn bestPermission;\n}\n\nfunction finalizePermission(aggregate: HookAggregateResult, bestPermission: PermissionDecision | undefined): void {\n\taggregate.permissionDecision = bestPermission;\n\tif (bestPermission !== \"ask\" && bestPermission !== \"defer\") return;\n\taggregate.blocked = true;\n\taggregate.reason = unsupportedPermissionReason(bestPermission);\n}\n\nexport function aggregateHookResults(input: HookInput, results: HookExecutionResult[]): HookAggregateResult {\n\tconst aggregate: HookAggregateResult = {\n\t\tcontinue: true,\n\t\tblocked: false,\n\t\tadditionalContext: [],\n\t\tsystemMessages: [],\n\t\tplainText: [],\n\t\tresults,\n\t};\n\tlet bestPermission: PermissionDecision | undefined;\n\tfor (const result of results.sort((left, right) => left.hook.order - right.hook.order)) {\n\t\tif (result.status !== \"completed\") continue;\n\t\tbestPermission = selectMoreRestrictivePermission(bestPermission, applyBlockingResult(input, result, aggregate));\n\t\tif (result.exitCode !== 0) continue;\n\t\tif (result.output.kind === \"text\") {\n\t\t\tappendPlainTextOutput(input, result.output.text, result.output.malformedJson, aggregate);\n\t\t\tcontinue;\n\t\t}\n\t\tif (result.output.kind !== \"json\") continue;\n\t\tconst output = result.output.value;\n\t\tapplyCommonJsonOutput(input, output, aggregate);\n\t\tconst specific = resolveSpecificOutput(input, result, output);\n\t\tconst context = getAdditionalContext(input, specific);\n\t\tif (context !== undefined) aggregate.additionalContext.push(context);\n\t\tbestPermission = applyEventSpecificOutput(input, result, output, specific, context, aggregate, bestPermission);\n\t}\n\tfinalizePermission(aggregate, bestPermission);\n\treturn aggregate;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAON,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAG3B,KAAK,WAAW,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC5C;AA+GD,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,SAAY,EAChB,KAAK,GAAE,SAAS,sBAAsB,EAAa,EACnD,QAAQ,SAAuC,GAC7C,kBAAkB,EAAE,CAatB;AAQD,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAElE;AAwPD,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAyB/E","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\nimport { matchHookValue } from \"./matcher.ts\";\nimport {\n\ttype CommandHookHandler,\n\tHOOK_EVENT_NAMES,\n\ttype HookDiagnostic,\n\ttype HookEventName,\n\ttype HookHandler,\n\ttype HookHandlerCommon,\n\ttype HookSettingsSource,\n\ttype HookSettingsSourceKind,\n\ttype HttpHookHandler,\n\ttype LoadedHookHandler,\n\ttype LoadedHooks,\n} from \"./types.ts\";\n\nexport interface LoadHooksOptions {\n\tcwd: string;\n\thome?: string;\n\t/** Active grip agent directory. Defaults to ~/.grip/agent. */\n\tagentDir?: string;\n\t/** Settings sources to discover. Defaults to trusted user hooks only. */\n\tsources?: readonly HookSettingsSourceKind[];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\nfunction isEvent(value: string): value is HookEventName {\n\treturn (HOOK_EVENT_NAMES as readonly string[]).includes(value);\n}\nfunction optionalCommon(value: Record<string, unknown>): boolean {\n\treturn (\n\t\t(value.timeout === undefined ||\n\t\t\t(typeof value.timeout === \"number\" && Number.isFinite(value.timeout) && value.timeout > 0)) &&\n\t\t(value.if === undefined || typeof value.if === \"string\") &&\n\t\t(value.statusMessage === undefined || typeof value.statusMessage === \"string\")\n\t);\n}\nfunction parseHookHandlerCommon(value: Record<string, unknown>): HookHandlerCommon | undefined {\n\tif (!optionalCommon(value)) return undefined;\n\treturn {\n\t\t...(typeof value.timeout === \"number\" ? { timeout: value.timeout } : {}),\n\t\t...(typeof value.if === \"string\" ? { if: value.if } : {}),\n\t\t...(typeof value.statusMessage === \"string\" ? { statusMessage: value.statusMessage } : {}),\n\t};\n}\n\nfunction parseCommandHookHandler(\n\tvalue: Record<string, unknown>,\n\tcommon: HookHandlerCommon,\n): CommandHookHandler | undefined {\n\t// Background hooks are outside Phase 0; do not silently run them synchronously.\n\tif (value.async !== undefined || value.asyncRewake !== undefined) return undefined;\n\tif (typeof value.command !== \"string\" || (value.args !== undefined && !isStringArray(value.args))) {\n\t\treturn undefined;\n\t}\n\tif (value.shell !== undefined && value.shell !== \"bash\" && value.shell !== \"powershell\") return undefined;\n\treturn {\n\t\ttype: \"command\",\n\t\tcommand: value.command,\n\t\t...common,\n\t\t...(value.args !== undefined ? { args: value.args } : {}),\n\t\t...(value.shell !== undefined ? { shell: value.shell } : {}),\n\t};\n}\n\nfunction parseHttpHookHandler(value: Record<string, unknown>, common: HookHandlerCommon): HttpHookHandler | undefined {\n\tif (typeof value.url !== \"string\") return undefined;\n\tlet headers: Record<string, string> | undefined;\n\tif (value.headers !== undefined) {\n\t\tif (!isObject(value.headers) || !Object.values(value.headers).every((item) => typeof item === \"string\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\theaders = Object.fromEntries(Object.entries(value.headers).map(([key, item]) => [key, String(item)]));\n\t}\n\tif (value.allowedEnvVars !== undefined && !isStringArray(value.allowedEnvVars)) return undefined;\n\treturn {\n\t\ttype: \"http\",\n\t\turl: value.url,\n\t\t...common,\n\t\t...(headers ? { headers } : {}),\n\t\t...(value.allowedEnvVars !== undefined ? { allowedEnvVars: value.allowedEnvVars } : {}),\n\t};\n}\n\nfunction parseHandler(value: unknown): HookHandler | undefined {\n\tif (!isObject(value) || typeof value.type !== \"string\") return undefined;\n\tconst common = parseHookHandlerCommon(value);\n\tif (!common) return undefined;\n\n\tswitch (value.type) {\n\t\tcase \"command\":\n\t\t\treturn parseCommandHookHandler(value, common);\n\t\tcase \"http\":\n\t\t\treturn parseHttpHookHandler(value, common);\n\t\tcase \"prompt\":\n\t\tcase \"agent\":\n\t\tcase \"mcp_tool\":\n\t\t\treturn { type: value.type, ...common };\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction canonical(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n\tif (isObject(value)) {\n\t\treturn `{${Object.keys(value)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)\n\t\t\t.join(\",\")}}`;\n\t}\n\treturn JSON.stringify(value) ?? \"undefined\";\n}\n\nfunction handlerKey(event: HookEventName, matcher: string | undefined, handler: HookHandler): string {\n\treturn `${event}\\0${matcher ?? \"\"}\\0${canonical(handler)}`;\n}\n\nfunction urlAllowed(url: string, allowlist: readonly string[]): boolean {\n\treturn allowlist.some((pattern) => {\n\t\tif (pattern === url) return true;\n\t\tconst expression = pattern\n\t\t\t.split(\"*\")\n\t\t\t.map((part) => part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n\t\t\t.join(\".*\");\n\t\treturn new RegExp(`^${expression}$`).test(url);\n\t});\n}\n\nexport function hookSettingsSources(\n\tcwd: string,\n\thome = homedir(),\n\tkinds: readonly HookSettingsSourceKind[] = [\"user\"],\n\tagentDir = join(home, CONFIG_DIR_NAME, \"agent\"),\n): HookSettingsSource[] {\n\tconst available: Record<\"user\" | \"project\" | \"local\", HookSettingsSource[]> = {\n\t\tuser: [\n\t\t\t{ kind: \"user\", path: join(agentDir, \"settings.json\") },\n\t\t\t{ kind: \"user\", path: join(home, \".claude\", \"settings.json\") },\n\t\t],\n\t\tproject: [\n\t\t\t{ kind: \"project\", path: join(cwd, CONFIG_DIR_NAME, \"settings.json\") },\n\t\t\t{ kind: \"project\", path: join(cwd, \".claude\", \"settings.json\") },\n\t\t],\n\t\tlocal: [{ kind: \"local\", path: join(cwd, \".claude\", \"settings.local.json\") }],\n\t};\n\treturn kinds.flatMap((kind) => (kind === \"host\" ? [] : available[kind]));\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** Clone and recursively freeze a host-provided hook snapshot. */\nexport function freezeLoadedHooks(loaded: LoadedHooks): LoadedHooks {\n\treturn deepFreeze(structuredClone(loaded));\n}\n\ninterface HookLoadState {\n\tdiagnostics: HookDiagnostic[];\n\thandlers: LoadedHookHandler[];\n\tallowedHttpHookUrls: string[];\n\thttpHookAllowedEnvVars: string[];\n\thasHttpUrlPolicy: boolean;\n\thasHttpEnvPolicy: boolean;\n\tseen: Set<string>;\n\tdisableAllHooks: boolean | undefined;\n\tnextOrder: number;\n}\n\ninterface ValidatedHookGroup {\n\thooks: unknown[];\n\tmatcher?: string;\n}\n\nasync function readHookSettings(\n\tsource: HookSettingsSource,\n\tdiagnostics: HookDiagnostic[],\n): Promise<Record<string, unknown> | undefined> {\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(source.path, \"utf8\");\n\t} catch (error) {\n\t\tif (isObject(error) && error.code === \"ENOENT\") return undefined;\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"read\",\n\t\t\tmessage: `Unable to read ${source.path}: ${String(error)}`,\n\t\t\tsource,\n\t\t});\n\t\treturn undefined;\n\t}\n\n\tlet settings: unknown;\n\ttry {\n\t\tsettings = JSON.parse(text);\n\t} catch (error) {\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"parse\",\n\t\t\tmessage: `Malformed JSON in ${source.path}: ${String(error)}`,\n\t\t\tsource,\n\t\t});\n\t\treturn undefined;\n\t}\n\tif (isObject(settings)) return settings;\n\tdiagnostics.push({\n\t\tlevel: \"error\",\n\t\tcode: \"schema\",\n\t\tmessage: `Expected an object in ${source.path}`,\n\t\tsource,\n\t});\n\treturn undefined;\n}\n\nfunction applyHookPolicySettings(\n\tsettings: Record<string, unknown>,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tif (settings.disableAllHooks !== undefined) {\n\t\tif (typeof settings.disableAllHooks === \"boolean\") state.disableAllHooks = settings.disableAllHooks;\n\t\telse {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"disableAllHooks must be a boolean\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n\tif (settings.allowedHttpHookUrls !== undefined) {\n\t\tif (isStringArray(settings.allowedHttpHookUrls)) {\n\t\t\tstate.hasHttpUrlPolicy = true;\n\t\t\tstate.allowedHttpHookUrls.push(...settings.allowedHttpHookUrls);\n\t\t} else {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"allowedHttpHookUrls must be a string array\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n\tif (settings.httpHookAllowedEnvVars !== undefined) {\n\t\tif (isStringArray(settings.httpHookAllowedEnvVars)) {\n\t\t\tstate.hasHttpEnvPolicy = true;\n\t\t\tstate.httpHookAllowedEnvVars.push(...settings.httpHookAllowedEnvVars);\n\t\t} else {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"httpHookAllowedEnvVars must be a string array\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction validateHookGroup(\n\tevent: HookEventName,\n\trawGroup: unknown,\n\tsource: HookSettingsSource,\n\tdiagnostics: HookDiagnostic[],\n): ValidatedHookGroup | undefined {\n\tif (\n\t\t!isObject(rawGroup) ||\n\t\t!Array.isArray(rawGroup.hooks) ||\n\t\t(rawGroup.matcher !== undefined && typeof rawGroup.matcher !== \"string\")\n\t) {\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Malformed ${event} hook group`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t\treturn undefined;\n\t}\n\tconst matcher = typeof rawGroup.matcher === \"string\" ? rawGroup.matcher : undefined;\n\tif (event !== \"UserPromptSubmit\" && event !== \"Stop\" && matcher !== undefined) {\n\t\tconst result = matchHookValue(matcher, \"\");\n\t\tif (result.error !== undefined) {\n\t\t\tdiagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"invalid-regex\",\n\t\t\t\tmessage: result.error,\n\t\t\t\tsource,\n\t\t\t\tevent,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn { hooks: rawGroup.hooks, ...(matcher !== undefined ? { matcher } : {}) };\n}\n\nfunction appendLoadedHookHandler(\n\trawHandler: unknown,\n\tevent: HookEventName,\n\tgroup: ValidatedHookGroup,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tconst handler = parseHandler(rawHandler);\n\tif (!handler) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Malformed ${event} hook handler`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t\treturn;\n\t}\n\tconst key = handlerKey(event, group.matcher, handler);\n\tif (state.seen.has(key)) return;\n\tstate.seen.add(key);\n\tstate.handlers.push({\n\t\tevent,\n\t\tmatcher: group.matcher,\n\t\thandler,\n\t\tsource,\n\t\torder: state.nextOrder++,\n\t});\n\tif (handler.type === \"prompt\" || handler.type === \"agent\" || handler.type === \"mcp_tool\") {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"warning\",\n\t\t\tcode: \"unsupported-handler\",\n\t\t\tmessage: `${handler.type} hook handlers are not supported and will not execute`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t}\n}\n\nfunction loadHookEvent(eventName: string, rawGroups: unknown, source: HookSettingsSource, state: HookLoadState): void {\n\tif (!isEvent(eventName)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"warning\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Unsupported hook event ${eventName}`,\n\t\t\tsource,\n\t\t});\n\t\treturn;\n\t}\n\tif (!Array.isArray(rawGroups)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `${eventName} must be an array`,\n\t\t\tsource,\n\t\t\tevent: eventName,\n\t\t});\n\t\treturn;\n\t}\n\tfor (const rawGroup of rawGroups) {\n\t\tconst group = validateHookGroup(eventName, rawGroup, source, state.diagnostics);\n\t\tif (!group) continue;\n\t\tfor (const rawHandler of group.hooks) {\n\t\t\tappendLoadedHookHandler(rawHandler, eventName, group, source, state);\n\t\t}\n\t}\n}\n\nfunction loadHookDefinitions(\n\tsettings: Record<string, unknown>,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tif (settings.hooks === undefined) return;\n\tif (!isObject(settings.hooks)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Expected an object-valued hooks field in ${source.path}`,\n\t\t\tsource,\n\t\t});\n\t\treturn;\n\t}\n\tfor (const [eventName, groups] of Object.entries(settings.hooks)) {\n\t\tloadHookEvent(eventName, groups, source, state);\n\t}\n}\n\nfunction applyHttpHookPolicies(state: HookLoadState): LoadedHookHandler[] {\n\treturn state.handlers.flatMap((loaded) => {\n\t\tif (loaded.handler.type !== \"http\") return [loaded];\n\t\tif (state.hasHttpUrlPolicy && !urlAllowed(loaded.handler.url, state.allowedHttpHookUrls)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"warning\",\n\t\t\t\tcode: \"policy\",\n\t\t\t\tmessage: `HTTP hook URL is not in allowedHttpHookUrls: ${loaded.handler.url}`,\n\t\t\t\tsource: loaded.source,\n\t\t\t\tevent: loaded.event,\n\t\t\t});\n\t\t\treturn [];\n\t\t}\n\t\tconst handlerAllowed = loaded.handler.allowedEnvVars;\n\t\tconst policyAllowed = state.hasHttpEnvPolicy ? state.httpHookAllowedEnvVars : (handlerAllowed ?? []);\n\t\tconst effective = handlerAllowed ? policyAllowed.filter((name) => handlerAllowed.includes(name)) : policyAllowed;\n\t\treturn [{ ...loaded, httpHookAllowedEnvVars: [...new Set(effective)] }];\n\t});\n}\n\nexport async function loadHooks(options: LoadHooksOptions): Promise<LoadedHooks> {\n\tconst sources = hookSettingsSources(options.cwd, options.home, options.sources, options.agentDir);\n\tconst state: HookLoadState = {\n\t\tdiagnostics: [],\n\t\thandlers: [],\n\t\tallowedHttpHookUrls: [],\n\t\thttpHookAllowedEnvVars: [],\n\t\thasHttpUrlPolicy: false,\n\t\thasHttpEnvPolicy: false,\n\t\tseen: new Set(),\n\t\tdisableAllHooks: undefined,\n\t\tnextOrder: 0,\n\t};\n\tfor (const source of sources) {\n\t\tconst settings = await readHookSettings(source, state.diagnostics);\n\t\tif (!settings) continue;\n\t\tapplyHookPolicySettings(settings, source, state);\n\t\tloadHookDefinitions(settings, source, state);\n\t}\n\tconst handlers = applyHttpHookPolicies(state);\n\treturn freezeLoadedHooks({\n\t\thandlers: state.disableAllHooks === true ? [] : handlers,\n\t\tdiagnostics: state.diagnostics,\n\t\tsources,\n\t});\n}\n"]}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAON,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAG3B,KAAK,WAAW,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC5C;AA+GD,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,SAAY,EAChB,KAAK,GAAE,SAAS,sBAAsB,EAAa,EACnD,QAAQ,SAAuC,GAC7C,kBAAkB,EAAE,CAatB;AAQD,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAElE;AAwPD,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAyB/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/core/hooks/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\nimport { matchHookValue } from \"./matcher.ts\";\nimport {\n\ttype CommandHookHandler,\n\tHOOK_EVENT_NAMES,\n\ttype HookDiagnostic,\n\ttype HookEventName,\n\ttype HookHandler,\n\ttype HookHandlerCommon,\n\ttype HookSettingsSource,\n\ttype HookSettingsSourceKind,\n\ttype HttpHookHandler,\n\ttype LoadedHookHandler,\n\ttype LoadedHooks,\n} from \"./types.ts\";\n\nexport interface LoadHooksOptions {\n\tcwd: string;\n\thome?: string;\n\t/** Active grip agent directory. Defaults to ~/.grip/agent. */\n\tagentDir?: string;\n\t/** Settings sources to discover. Defaults to trusted user hooks only. */\n\tsources?: readonly HookSettingsSourceKind[];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\nfunction isEvent(value: string): value is HookEventName {\n\treturn (HOOK_EVENT_NAMES as readonly string[]).includes(value);\n}\nfunction optionalCommon(value: Record<string, unknown>): boolean {\n\treturn (\n\t\t(value.timeout === undefined ||\n\t\t\t(typeof value.timeout === \"number\" && Number.isFinite(value.timeout) && value.timeout > 0)) &&\n\t\t(value.if === undefined || typeof value.if === \"string\") &&\n\t\t(value.statusMessage === undefined || typeof value.statusMessage === \"string\")\n\t);\n}\nfunction parseHookHandlerCommon(value: Record<string, unknown>): HookHandlerCommon | undefined {\n\tif (!optionalCommon(value)) return undefined;\n\treturn {\n\t\t...(typeof value.timeout === \"number\" ? { timeout: value.timeout } : {}),\n\t\t...(typeof value.if === \"string\" ? { if: value.if } : {}),\n\t\t...(typeof value.statusMessage === \"string\" ? { statusMessage: value.statusMessage } : {}),\n\t};\n}\n\nfunction parseCommandHookHandler(\n\tvalue: Record<string, unknown>,\n\tcommon: HookHandlerCommon,\n): CommandHookHandler | undefined {\n\t// Background hooks are outside Phase 0; do not silently run them synchronously.\n\tif (value.async !== undefined || value.asyncRewake !== undefined) return undefined;\n\tif (typeof value.command !== \"string\" || (value.args !== undefined && !isStringArray(value.args))) {\n\t\treturn undefined;\n\t}\n\tif (value.shell !== undefined && value.shell !== \"bash\" && value.shell !== \"powershell\") return undefined;\n\treturn {\n\t\ttype: \"command\",\n\t\tcommand: value.command,\n\t\t...common,\n\t\t...(value.args !== undefined ? { args: value.args } : {}),\n\t\t...(value.shell !== undefined ? { shell: value.shell } : {}),\n\t};\n}\n\nfunction parseHttpHookHandler(value: Record<string, unknown>, common: HookHandlerCommon): HttpHookHandler | undefined {\n\tif (typeof value.url !== \"string\") return undefined;\n\tlet headers: Record<string, string> | undefined;\n\tif (value.headers !== undefined) {\n\t\tif (!isObject(value.headers) || !Object.values(value.headers).every((item) => typeof item === \"string\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\theaders = Object.fromEntries(Object.entries(value.headers).map(([key, item]) => [key, String(item)]));\n\t}\n\tif (value.allowedEnvVars !== undefined && !isStringArray(value.allowedEnvVars)) return undefined;\n\treturn {\n\t\ttype: \"http\",\n\t\turl: value.url,\n\t\t...common,\n\t\t...(headers ? { headers } : {}),\n\t\t...(value.allowedEnvVars !== undefined ? { allowedEnvVars: value.allowedEnvVars } : {}),\n\t};\n}\n\nfunction parseHandler(value: unknown): HookHandler | undefined {\n\tif (!isObject(value) || typeof value.type !== \"string\") return undefined;\n\tconst common = parseHookHandlerCommon(value);\n\tif (!common) return undefined;\n\n\tswitch (value.type) {\n\t\tcase \"command\":\n\t\t\treturn parseCommandHookHandler(value, common);\n\t\tcase \"http\":\n\t\t\treturn parseHttpHookHandler(value, common);\n\t\tcase \"prompt\":\n\t\tcase \"agent\":\n\t\tcase \"mcp_tool\":\n\t\t\treturn { type: value.type, ...common };\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction canonical(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n\tif (isObject(value)) {\n\t\treturn `{${Object.keys(value)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)\n\t\t\t.join(\",\")}}`;\n\t}\n\treturn JSON.stringify(value) ?? \"undefined\";\n}\n\nfunction handlerKey(event: HookEventName, matcher: string | undefined, handler: HookHandler): string {\n\treturn `${event}\\0${matcher ?? \"\"}\\0${canonical(handler)}`;\n}\n\nfunction urlAllowed(url: string, allowlist: readonly string[]): boolean {\n\treturn allowlist.some((pattern) => {\n\t\tif (pattern === url) return true;\n\t\tconst expression = pattern\n\t\t\t.split(\"*\")\n\t\t\t.map((part) => part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n\t\t\t.join(\".*\");\n\t\treturn new RegExp(`^${expression}$`).test(url);\n\t});\n}\n\nexport function hookSettingsSources(\n\tcwd: string,\n\thome = homedir(),\n\tkinds: readonly HookSettingsSourceKind[] = [\"user\"],\n\tagentDir = join(home, CONFIG_DIR_NAME, \"agent\"),\n): HookSettingsSource[] {\n\tconst available: Record<\"user\" | \"project\" | \"local\", HookSettingsSource[]> = {\n\t\tuser: [\n\t\t\t{ kind: \"user\", path: join(agentDir, \"settings.json\") },\n\t\t\t{ kind: \"user\", path: join(home, \".claude\", \"settings.json\") },\n\t\t],\n\t\tproject: [\n\t\t\t{ kind: \"project\", path: join(cwd, CONFIG_DIR_NAME, \"settings.json\") },\n\t\t\t{ kind: \"project\", path: join(cwd, \".claude\", \"settings.json\") },\n\t\t],\n\t\tlocal: [{ kind: \"local\", path: join(cwd, \".claude\", \"settings.local.json\") }],\n\t};\n\treturn kinds.flatMap((kind) => (kind === \"host\" ? [] : available[kind]));\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** Clone and recursively freeze a host-provided hook snapshot. */\nexport function freezeLoadedHooks(loaded: LoadedHooks): LoadedHooks {\n\treturn deepFreeze(structuredClone(loaded));\n}\n\ninterface HookLoadState {\n\tdiagnostics: HookDiagnostic[];\n\thandlers: LoadedHookHandler[];\n\tallowedHttpHookUrls: string[];\n\thttpHookAllowedEnvVars: string[];\n\thasHttpUrlPolicy: boolean;\n\thasHttpEnvPolicy: boolean;\n\tseen: Set<string>;\n\tdisableAllHooks: boolean | undefined;\n\tnextOrder: number;\n}\n\ninterface ValidatedHookGroup {\n\thooks: unknown[];\n\tmatcher?: string;\n}\n\nasync function readHookSettings(\n\tsource: HookSettingsSource,\n\tdiagnostics: HookDiagnostic[],\n): Promise<Record<string, unknown> | undefined> {\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(source.path, \"utf8\");\n\t} catch (error) {\n\t\tif (isObject(error) && error.code === \"ENOENT\") return undefined;\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"read\",\n\t\t\tmessage: `Unable to read ${source.path}: ${String(error)}`,\n\t\t\tsource,\n\t\t});\n\t\treturn undefined;\n\t}\n\n\tlet settings: unknown;\n\ttry {\n\t\tsettings = JSON.parse(text);\n\t} catch (error) {\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"parse\",\n\t\t\tmessage: `Malformed JSON in ${source.path}: ${String(error)}`,\n\t\t\tsource,\n\t\t});\n\t\treturn undefined;\n\t}\n\tif (isObject(settings)) return settings;\n\tdiagnostics.push({\n\t\tlevel: \"error\",\n\t\tcode: \"schema\",\n\t\tmessage: `Expected an object in ${source.path}`,\n\t\tsource,\n\t});\n\treturn undefined;\n}\n\nfunction applyHookPolicySettings(\n\tsettings: Record<string, unknown>,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tif (settings.disableAllHooks !== undefined) {\n\t\tif (typeof settings.disableAllHooks === \"boolean\") state.disableAllHooks = settings.disableAllHooks;\n\t\telse {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"disableAllHooks must be a boolean\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n\tif (settings.allowedHttpHookUrls !== undefined) {\n\t\tif (isStringArray(settings.allowedHttpHookUrls)) {\n\t\t\tstate.hasHttpUrlPolicy = true;\n\t\t\tstate.allowedHttpHookUrls.push(...settings.allowedHttpHookUrls);\n\t\t} else {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"allowedHttpHookUrls must be a string array\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n\tif (settings.httpHookAllowedEnvVars !== undefined) {\n\t\tif (isStringArray(settings.httpHookAllowedEnvVars)) {\n\t\t\tstate.hasHttpEnvPolicy = true;\n\t\t\tstate.httpHookAllowedEnvVars.push(...settings.httpHookAllowedEnvVars);\n\t\t} else {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"httpHookAllowedEnvVars must be a string array\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction validateHookGroup(\n\tevent: HookEventName,\n\trawGroup: unknown,\n\tsource: HookSettingsSource,\n\tdiagnostics: HookDiagnostic[],\n): ValidatedHookGroup | undefined {\n\tif (\n\t\t!isObject(rawGroup) ||\n\t\t!Array.isArray(rawGroup.hooks) ||\n\t\t(rawGroup.matcher !== undefined && typeof rawGroup.matcher !== \"string\")\n\t) {\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Malformed ${event} hook group`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t\treturn undefined;\n\t}\n\tconst matcher = typeof rawGroup.matcher === \"string\" ? rawGroup.matcher : undefined;\n\tif (event !== \"UserPromptSubmit\" && event !== \"Stop\" && matcher !== undefined) {\n\t\tconst result = matchHookValue(matcher, \"\");\n\t\tif (result.error !== undefined) {\n\t\t\tdiagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"invalid-regex\",\n\t\t\t\tmessage: result.error,\n\t\t\t\tsource,\n\t\t\t\tevent,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn { hooks: rawGroup.hooks, ...(matcher !== undefined ? { matcher } : {}) };\n}\n\nfunction appendLoadedHookHandler(\n\trawHandler: unknown,\n\tevent: HookEventName,\n\tgroup: ValidatedHookGroup,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tconst handler = parseHandler(rawHandler);\n\tif (!handler) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Malformed ${event} hook handler`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t\treturn;\n\t}\n\tconst key = handlerKey(event, group.matcher, handler);\n\tif (state.seen.has(key)) return;\n\tstate.seen.add(key);\n\tstate.handlers.push({\n\t\tevent,\n\t\tmatcher: group.matcher,\n\t\thandler,\n\t\tsource,\n\t\torder: state.nextOrder++,\n\t});\n\tif (handler.type === \"prompt\" || handler.type === \"agent\" || handler.type === \"mcp_tool\") {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"warning\",\n\t\t\tcode: \"unsupported-handler\",\n\t\t\tmessage: `${handler.type} hook handlers are not supported and will not execute`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t}\n}\n\nfunction loadHookEvent(eventName: string, rawGroups: unknown, source: HookSettingsSource, state: HookLoadState): void {\n\tif (!isEvent(eventName)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"warning\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Unsupported hook event ${eventName}`,\n\t\t\tsource,\n\t\t});\n\t\treturn;\n\t}\n\tif (!Array.isArray(rawGroups)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `${eventName} must be an array`,\n\t\t\tsource,\n\t\t\tevent: eventName,\n\t\t});\n\t\treturn;\n\t}\n\tfor (const rawGroup of rawGroups) {\n\t\tconst group = validateHookGroup(eventName, rawGroup, source, state.diagnostics);\n\t\tif (!group) continue;\n\t\tfor (const rawHandler of group.hooks) {\n\t\t\tappendLoadedHookHandler(rawHandler, eventName, group, source, state);\n\t\t}\n\t}\n}\n\nfunction loadHookDefinitions(\n\tsettings: Record<string, unknown>,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tif (settings.hooks === undefined) return;\n\tif (!isObject(settings.hooks)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Expected an object-valued hooks field in ${source.path}`,\n\t\t\tsource,\n\t\t});\n\t\treturn;\n\t}\n\tfor (const [eventName, groups] of Object.entries(settings.hooks)) {\n\t\tloadHookEvent(eventName, groups, source, state);\n\t}\n}\n\nfunction applyHttpHookPolicies(state: HookLoadState): LoadedHookHandler[] {\n\treturn state.handlers.flatMap((loaded) => {\n\t\tif (loaded.handler.type !== \"http\") return [loaded];\n\t\tif (state.hasHttpUrlPolicy && !urlAllowed(loaded.handler.url, state.allowedHttpHookUrls)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"warning\",\n\t\t\t\tcode: \"policy\",\n\t\t\t\tmessage: `HTTP hook URL is not in allowedHttpHookUrls: ${loaded.handler.url}`,\n\t\t\t\tsource: loaded.source,\n\t\t\t\tevent: loaded.event,\n\t\t\t});\n\t\t\treturn [];\n\t\t}\n\t\tconst handlerAllowed = loaded.handler.allowedEnvVars;\n\t\tconst policyAllowed = state.hasHttpEnvPolicy ? state.httpHookAllowedEnvVars : (handlerAllowed ?? []);\n\t\tconst effective = handlerAllowed ? policyAllowed.filter((name) => handlerAllowed.includes(name)) : policyAllowed;\n\t\treturn [{ ...loaded, httpHookAllowedEnvVars: [...new Set(effective)] }];\n\t});\n}\n\nexport async function loadHooks(options: LoadHooksOptions): Promise<LoadedHooks> {\n\tconst sources = hookSettingsSources(options.cwd, options.home, options.sources, options.agentDir);\n\tconst state: HookLoadState = {\n\t\tdiagnostics: [],\n\t\thandlers: [],\n\t\tallowedHttpHookUrls: [],\n\t\thttpHookAllowedEnvVars: [],\n\t\thasHttpUrlPolicy: false,\n\t\thasHttpEnvPolicy: false,\n\t\tseen: new Set(),\n\t\tdisableAllHooks: undefined,\n\t\tnextOrder: 0,\n\t};\n\tfor (const source of sources) {\n\t\tconst settings = await readHookSettings(source, state.diagnostics);\n\t\tif (!settings) continue;\n\t\tapplyHookPolicySettings(settings, source, state);\n\t\tloadHookDefinitions(settings, source, state);\n\t}\n\tconst handlers = applyHttpHookPolicies(state);\n\treturn freezeLoadedHooks({\n\t\thandlers: state.disableAllHooks === true ? [] : handlers,\n\t\tdiagnostics: state.diagnostics,\n\t\tsources,\n\t});\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/core/hooks/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\nimport { matchHookValue } from \"./matcher.ts\";\nimport {\n\ttype CommandHookHandler,\n\tHOOK_EVENT_NAMES,\n\ttype HookDiagnostic,\n\ttype HookEventName,\n\ttype HookHandler,\n\ttype HookHandlerCommon,\n\ttype HookSettingsSource,\n\ttype HookSettingsSourceKind,\n\ttype HttpHookHandler,\n\ttype LoadedHookHandler,\n\ttype LoadedHooks,\n} from \"./types.ts\";\n\nexport interface LoadHooksOptions {\n\tcwd: string;\n\thome?: string;\n\t/** Active grip agent directory. Defaults to ~/.grip/agent. */\n\tagentDir?: string;\n\t/** Settings sources to discover. Defaults to trusted user hooks only. */\n\tsources?: readonly HookSettingsSourceKind[];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\nfunction isEvent(value: string): value is HookEventName {\n\treturn (HOOK_EVENT_NAMES as readonly string[]).includes(value);\n}\nfunction optionalCommon(value: Record<string, unknown>): boolean {\n\treturn (\n\t\t(value.timeout === undefined ||\n\t\t\t(typeof value.timeout === \"number\" && Number.isFinite(value.timeout) && value.timeout > 0)) &&\n\t\t(value.if === undefined || typeof value.if === \"string\") &&\n\t\t(value.statusMessage === undefined || typeof value.statusMessage === \"string\")\n\t);\n}\nfunction parseHookHandlerCommon(value: Record<string, unknown>): HookHandlerCommon | undefined {\n\tif (!optionalCommon(value)) return undefined;\n\treturn {\n\t\t...(typeof value.timeout === \"number\" ? { timeout: value.timeout } : {}),\n\t\t...(typeof value.if === \"string\" ? { if: value.if } : {}),\n\t\t...(typeof value.statusMessage === \"string\" ? { statusMessage: value.statusMessage } : {}),\n\t};\n}\n\nfunction parseCommandHookHandler(\n\tvalue: Record<string, unknown>,\n\tcommon: HookHandlerCommon,\n): CommandHookHandler | undefined {\n\t// Background hooks are outside Phase 0; do not silently run them synchronously.\n\tif (value.async !== undefined || value.asyncRewake !== undefined) return undefined;\n\tif (typeof value.command !== \"string\" || (value.args !== undefined && !isStringArray(value.args))) {\n\t\treturn undefined;\n\t}\n\tif (value.shell !== undefined && value.shell !== \"bash\" && value.shell !== \"powershell\") return undefined;\n\treturn {\n\t\ttype: \"command\",\n\t\tcommand: value.command,\n\t\t...common,\n\t\t...(value.args !== undefined ? { args: value.args } : {}),\n\t\t...(value.shell !== undefined ? { shell: value.shell } : {}),\n\t};\n}\n\nfunction parseHttpHookHandler(value: Record<string, unknown>, common: HookHandlerCommon): HttpHookHandler | undefined {\n\tif (typeof value.url !== \"string\") return undefined;\n\tlet headers: Record<string, string> | undefined;\n\tif (value.headers !== undefined) {\n\t\tif (!isObject(value.headers) || !Object.values(value.headers).every((item) => typeof item === \"string\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\theaders = Object.fromEntries(Object.entries(value.headers).map(([key, item]) => [key, String(item)]));\n\t}\n\tif (value.allowedEnvVars !== undefined && !isStringArray(value.allowedEnvVars)) return undefined;\n\treturn {\n\t\ttype: \"http\",\n\t\turl: value.url,\n\t\t...common,\n\t\t...(headers ? { headers } : {}),\n\t\t...(value.allowedEnvVars !== undefined ? { allowedEnvVars: value.allowedEnvVars } : {}),\n\t};\n}\n\nfunction parseHandler(value: unknown): HookHandler | undefined {\n\tif (!isObject(value) || typeof value.type !== \"string\") return undefined;\n\tconst common = parseHookHandlerCommon(value);\n\tif (!common) return undefined;\n\n\tswitch (value.type) {\n\t\tcase \"command\":\n\t\t\treturn parseCommandHookHandler(value, common);\n\t\tcase \"http\":\n\t\t\treturn parseHttpHookHandler(value, common);\n\t\tcase \"prompt\":\n\t\tcase \"agent\":\n\t\tcase \"mcp_tool\":\n\t\t\treturn { type: value.type, ...common };\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction canonical(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n\tif (isObject(value)) {\n\t\treturn `{${Object.keys(value)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)\n\t\t\t.join(\",\")}}`;\n\t}\n\treturn JSON.stringify(value) ?? \"undefined\";\n}\n\nfunction handlerKey(event: HookEventName, matcher: string | undefined, handler: HookHandler): string {\n\treturn `${event}\\0${matcher ?? \"\"}\\0${canonical(handler)}`;\n}\n\nfunction urlAllowed(url: string, allowlist: readonly string[]): boolean {\n\treturn allowlist.some((pattern) => {\n\t\tif (pattern === url) return true;\n\t\tconst expression = pattern\n\t\t\t.split(\"*\")\n\t\t\t.map((part) => part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n\t\t\t.join(\".*\");\n\t\treturn new RegExp(`^${expression}$`).test(url);\n\t});\n}\n\nexport function hookSettingsSources(\n\tcwd: string,\n\thome = homedir(),\n\tkinds: readonly HookSettingsSourceKind[] = [\"user\"],\n\tagentDir = join(home, CONFIG_DIR_NAME, \"agent\"),\n): HookSettingsSource[] {\n\tconst available: Record<\"user\" | \"project\" | \"local\", HookSettingsSource[]> = {\n\t\tuser: [\n\t\t\t{ kind: \"user\", path: join(agentDir, \"settings.json\") },\n\t\t\t{ kind: \"user\", path: join(home, \".claude\", \"settings.json\") },\n\t\t],\n\t\tproject: [\n\t\t\t{ kind: \"project\", path: join(cwd, CONFIG_DIR_NAME, \"settings.json\") },\n\t\t\t{ kind: \"project\", path: join(cwd, \".claude\", \"settings.json\") },\n\t\t],\n\t\tlocal: [{ kind: \"local\", path: join(cwd, \".claude\", \"settings.local.json\") }],\n\t};\n\treturn kinds.flatMap((kind) => (kind === \"host\" ? [] : available[kind]));\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** Clone and recursively freeze a host-provided hook snapshot. */\nexport function freezeLoadedHooks(loaded: LoadedHooks): LoadedHooks {\n\treturn deepFreeze(structuredClone(loaded));\n}\n\ninterface HookLoadState {\n\tdiagnostics: HookDiagnostic[];\n\thandlers: LoadedHookHandler[];\n\tallowedHttpHookUrls: string[];\n\thttpHookAllowedEnvVars: string[];\n\thasHttpUrlPolicy: boolean;\n\thasHttpEnvPolicy: boolean;\n\tseen: Set<string>;\n\tdisableAllHooks: boolean | undefined;\n\tnextOrder: number;\n}\n\ninterface ValidatedHookGroup {\n\thooks: unknown[];\n\tmatcher?: string;\n}\n\nasync function readHookSettings(\n\tsource: HookSettingsSource,\n\tdiagnostics: HookDiagnostic[],\n): Promise<Record<string, unknown> | undefined> {\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(source.path, \"utf8\");\n\t} catch (error) {\n\t\tif (isObject(error) && error.code === \"ENOENT\") return undefined;\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"read\",\n\t\t\tmessage: `Unable to read ${source.path}: ${String(error)}`,\n\t\t\tsource,\n\t\t});\n\t\treturn undefined;\n\t}\n\n\tlet settings: unknown;\n\ttry {\n\t\tsettings = JSON.parse(text);\n\t} catch (error) {\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"parse\",\n\t\t\tmessage: `Malformed JSON in ${source.path}: ${String(error)}`,\n\t\t\tsource,\n\t\t});\n\t\treturn undefined;\n\t}\n\tif (isObject(settings)) return settings;\n\tdiagnostics.push({\n\t\tlevel: \"error\",\n\t\tcode: \"schema\",\n\t\tmessage: `Expected an object in ${source.path}`,\n\t\tsource,\n\t});\n\treturn undefined;\n}\n\nfunction applyHookPolicySettings(\n\tsettings: Record<string, unknown>,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tif (settings.disableAllHooks !== undefined) {\n\t\tif (typeof settings.disableAllHooks === \"boolean\") state.disableAllHooks = settings.disableAllHooks;\n\t\telse {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"disableAllHooks must be a boolean\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n\tif (settings.allowedHttpHookUrls !== undefined) {\n\t\tif (isStringArray(settings.allowedHttpHookUrls)) {\n\t\t\tstate.hasHttpUrlPolicy = true;\n\t\t\tstate.allowedHttpHookUrls.push(...settings.allowedHttpHookUrls);\n\t\t} else {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"allowedHttpHookUrls must be a string array\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n\tif (settings.httpHookAllowedEnvVars !== undefined) {\n\t\tif (isStringArray(settings.httpHookAllowedEnvVars)) {\n\t\t\tstate.hasHttpEnvPolicy = true;\n\t\t\tstate.httpHookAllowedEnvVars.push(...settings.httpHookAllowedEnvVars);\n\t\t} else {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"schema\",\n\t\t\t\tmessage: \"httpHookAllowedEnvVars must be a string array\",\n\t\t\t\tsource,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction validateHookGroup(\n\tevent: HookEventName,\n\trawGroup: unknown,\n\tsource: HookSettingsSource,\n\tdiagnostics: HookDiagnostic[],\n): ValidatedHookGroup | undefined {\n\tif (\n\t\t!isObject(rawGroup) ||\n\t\t!Array.isArray(rawGroup.hooks) ||\n\t\t(rawGroup.matcher !== undefined && typeof rawGroup.matcher !== \"string\")\n\t) {\n\t\tdiagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Malformed ${event} hook group`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t\treturn undefined;\n\t}\n\tconst matcher = typeof rawGroup.matcher === \"string\" ? rawGroup.matcher : undefined;\n\tif (event !== \"UserPromptSubmit\" && event !== \"Stop\" && matcher !== undefined) {\n\t\tconst result = matchHookValue(matcher, \"\");\n\t\tif (result.error !== undefined) {\n\t\t\tdiagnostics.push({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tcode: \"invalid-regex\",\n\t\t\t\tmessage: result.error,\n\t\t\t\tsource,\n\t\t\t\tevent,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn { hooks: rawGroup.hooks, ...(matcher !== undefined ? { matcher } : {}) };\n}\n\nfunction appendLoadedHookHandler(\n\trawHandler: unknown,\n\tevent: HookEventName,\n\tgroup: ValidatedHookGroup,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tconst handler = parseHandler(rawHandler);\n\tif (!handler) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Malformed ${event} hook handler`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t\treturn;\n\t}\n\tconst key = handlerKey(event, group.matcher, handler);\n\tif (state.seen.has(key)) return;\n\tstate.seen.add(key);\n\tstate.handlers.push({\n\t\tevent,\n\t\tmatcher: group.matcher,\n\t\thandler,\n\t\tsource,\n\t\torder: state.nextOrder++,\n\t});\n\tif (handler.type === \"prompt\" || handler.type === \"agent\" || handler.type === \"mcp_tool\") {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"warning\",\n\t\t\tcode: \"unsupported-handler\",\n\t\t\tmessage: `${handler.type} hook handlers are not supported and will not execute`,\n\t\t\tsource,\n\t\t\tevent,\n\t\t});\n\t}\n}\n\nfunction loadHookEvent(eventName: string, rawGroups: unknown, source: HookSettingsSource, state: HookLoadState): void {\n\tif (!isEvent(eventName)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"warning\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Unsupported hook event ${eventName}`,\n\t\t\tsource,\n\t\t});\n\t\treturn;\n\t}\n\tif (!Array.isArray(rawGroups)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `${eventName} must be an array`,\n\t\t\tsource,\n\t\t\tevent: eventName,\n\t\t});\n\t\treturn;\n\t}\n\tfor (const rawGroup of rawGroups) {\n\t\tconst group = validateHookGroup(eventName, rawGroup, source, state.diagnostics);\n\t\tif (!group) continue;\n\t\tfor (const rawHandler of group.hooks) {\n\t\t\tappendLoadedHookHandler(rawHandler, eventName, group, source, state);\n\t\t}\n\t}\n}\n\nfunction loadHookDefinitions(\n\tsettings: Record<string, unknown>,\n\tsource: HookSettingsSource,\n\tstate: HookLoadState,\n): void {\n\tif (settings.hooks === undefined) return;\n\tif (!isObject(settings.hooks)) {\n\t\tstate.diagnostics.push({\n\t\t\tlevel: \"error\",\n\t\t\tcode: \"schema\",\n\t\t\tmessage: `Expected an object-valued hooks field in ${source.path}`,\n\t\t\tsource,\n\t\t});\n\t\treturn;\n\t}\n\tfor (const [eventName, groups] of Object.entries(settings.hooks)) {\n\t\tloadHookEvent(eventName, groups, source, state);\n\t}\n}\n\nfunction applyHttpHookPolicies(state: HookLoadState): LoadedHookHandler[] {\n\treturn state.handlers.flatMap((loaded) => {\n\t\tif (loaded.handler.type !== \"http\") return [loaded];\n\t\tif (state.hasHttpUrlPolicy && !urlAllowed(loaded.handler.url, state.allowedHttpHookUrls)) {\n\t\t\tstate.diagnostics.push({\n\t\t\t\tlevel: \"warning\",\n\t\t\t\tcode: \"policy\",\n\t\t\t\tmessage: `HTTP hook URL is not in allowedHttpHookUrls: ${loaded.handler.url}`,\n\t\t\t\tsource: loaded.source,\n\t\t\t\tevent: loaded.event,\n\t\t\t});\n\t\t\treturn [];\n\t\t}\n\t\tconst handlerAllowed = loaded.handler.allowedEnvVars;\n\t\tconst policyAllowed = state.hasHttpEnvPolicy ? state.httpHookAllowedEnvVars : (handlerAllowed ?? []);\n\t\tconst effective = handlerAllowed ? policyAllowed.filter((name) => handlerAllowed.includes(name)) : policyAllowed;\n\t\treturn [{ ...loaded, httpHookAllowedEnvVars: [...new Set(effective)] }];\n\t});\n}\n\nexport async function loadHooks(options: LoadHooksOptions): Promise<LoadedHooks> {\n\tconst sources = hookSettingsSources(options.cwd, options.home, options.sources, options.agentDir);\n\tconst state: HookLoadState = {\n\t\tdiagnostics: [],\n\t\thandlers: [],\n\t\tallowedHttpHookUrls: [],\n\t\thttpHookAllowedEnvVars: [],\n\t\thasHttpUrlPolicy: false,\n\t\thasHttpEnvPolicy: false,\n\t\tseen: new Set(),\n\t\tdisableAllHooks: undefined,\n\t\tnextOrder: 0,\n\t};\n\tfor (const source of sources) {\n\t\tconst settings = await readHookSettings(source, state.diagnostics);\n\t\tif (!settings) continue;\n\t\tapplyHookPolicySettings(settings, source, state);\n\t\tloadHookDefinitions(settings, source, state);\n\t}\n\tconst handlers = applyHttpHookPolicies(state);\n\treturn freezeLoadedHooks({\n\t\thandlers: state.disableAllHooks === true ? [] : handlers,\n\t\tdiagnostics: state.diagnostics,\n\t\tsources,\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAIX,mBAAmB,EAGnB,SAAS,EACT,wBAAwB,EACxB,cAAc,EAGd,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,wCAAwC,KAAK,CAAC;AAC3D,eAAO,MAAM,wCAAwC,MAAM,CAAC;AAC5D,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAmDzD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAS3E;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAIlE;AAOD,wBAAgB,wBAAwB,CAAC,MAAM,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,UAAU,CAQnG;AAurBD,wBAAsB,WAAW,CAChC,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAY9B;AAED,wBAAsB,oBAAoB,CACzC,KAAK,EAAE,SAAS,iBAAiB,EAAE,EACnC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAqBhC","sourcesContent":["import { type ChildProcessWithoutNullStreams, spawn } from \"node:child_process\";\nimport { performance } from \"node:perf_hooks\";\nimport type { PortablePathFlavor } from \"../lsp/portable-path.ts\";\nimport { matchesHookIf, matchesHookInput } from \"./matcher.ts\";\nimport type {\n\tCommandHookHandler,\n\tHookDiagnostic,\n\tHookDiagnosticCode,\n\tHookExecutionResult,\n\tHookExecutionStatus,\n\tHookHandlerCommon,\n\tHookInput,\n\tHookOutputClassification,\n\tHookRunOptions,\n\tHookStructuredOutput,\n\tHttpHookHandler,\n\tLoadedHookHandler,\n} from \"./types.ts\";\n\nexport const DEFAULT_HOOK_TIMEOUT_SECONDS = 600;\nexport const DEFAULT_USER_PROMPT_HOOK_TIMEOUT_SECONDS = 30;\nexport const DEFAULT_SESSION_END_HOOK_TIMEOUT_SECONDS = 1.5;\nexport const MAX_SESSION_END_HOOK_TIMEOUT_SECONDS = 60;\nexport const DEFAULT_MAX_HOOK_OUTPUT_BYTES = 1024 * 1024;\n\ninterface CompletedCommandState {\n\tstdout: Buffer;\n\tstderr: Buffer;\n\tstdoutTruncated: boolean;\n\tstderrTruncated: boolean;\n\toutputLimitExceeded: boolean;\n\ttimedOut: boolean;\n\tcancelled: boolean;\n}\n\ninterface BoundedBufferAppendResult {\n\tvalue: Buffer;\n\ttruncated: boolean;\n}\n\ntype WindowsProcessTreeTerminator = (pid: number) => void;\n\nfunction forceTerminateChildProcess(\n\tchild: ChildProcessWithoutNullStreams,\n\tplatform: NodeJS.Platform,\n\tterminateWindowsTree: WindowsProcessTreeTerminator,\n): void {\n\tif (child.pid && platform === \"win32\") {\n\t\tterminateWindowsTree(child.pid);\n\t} else if (child.pid) {\n\t\ttry {\n\t\t\tprocess.kill(-child.pid, \"SIGKILL\");\n\t\t} catch {\n\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(\"SIGKILL\");\n\t\t}\n\t} else if (child.exitCode === null && child.signalCode === null) {\n\t\tchild.kill(\"SIGKILL\");\n\t}\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction isStructuredOutput(value: unknown): value is HookStructuredOutput {\n\tif (!isObject(value)) return false;\n\treturn (\n\t\t(value.continue === undefined || typeof value.continue === \"boolean\") &&\n\t\t(value.stopReason === undefined || typeof value.stopReason === \"string\") &&\n\t\t(value.systemMessage === undefined || typeof value.systemMessage === \"string\") &&\n\t\t(value.decision === undefined || typeof value.decision === \"string\") &&\n\t\t(value.reason === undefined || typeof value.reason === \"string\") &&\n\t\t(value.hookSpecificOutput === undefined || isObject(value.hookSpecificOutput))\n\t);\n}\nexport function classifyHookOutput(stdout: string): HookOutputClassification {\n\tif (stdout.length === 0) return { kind: \"empty\" };\n\tif (!stdout.trimStart().startsWith(\"{\")) return { kind: \"text\", text: stdout, malformedJson: false };\n\ttry {\n\t\tconst value: unknown = JSON.parse(stdout);\n\t\treturn isStructuredOutput(value) ? { kind: \"json\", value } : { kind: \"text\", text: stdout, malformedJson: true };\n\t} catch {\n\t\treturn { kind: \"text\", text: stdout, malformedJson: true };\n\t}\n}\n\nexport function defaultHookTimeoutSeconds(input: HookInput): number {\n\tif (input.hook_event_name === \"SessionEnd\") return DEFAULT_SESSION_END_HOOK_TIMEOUT_SECONDS;\n\tif (input.hook_event_name === \"UserPromptSubmit\") return DEFAULT_USER_PROMPT_HOOK_TIMEOUT_SECONDS;\n\treturn DEFAULT_HOOK_TIMEOUT_SECONDS;\n}\n\nfunction hookTimeoutSeconds(handler: HookHandlerCommon, input: HookInput, options?: HookRunOptions): number {\n\tif (options?.timeoutSeconds !== undefined) return options.timeoutSeconds;\n\tconst timeout = handler.timeout ?? defaultHookTimeoutSeconds(input);\n\treturn input.hook_event_name === \"SessionEnd\" ? Math.min(timeout, MAX_SESSION_END_HOOK_TIMEOUT_SECONDS) : timeout;\n}\nexport function sanitizedHookEnvironment(source: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n\tconst result: NodeJS.ProcessEnv = {};\n\tfor (const [key, value] of Object.entries(source)) {\n\t\tif (key.startsWith(\"OTEL_\")) continue;\n\t\tif (/^(?:GRIP|PI)_.*(?:TOKEN|CREDENTIAL|API_KEY|SECRET|PASSWORD)/i.test(key)) continue;\n\t\tresult[key] = value;\n\t}\n\treturn result;\n}\nfunction appendBounded(current: Buffer, chunk: Buffer, maximum: number): BoundedBufferAppendResult {\n\tif (current.length >= maximum) return { value: current, truncated: chunk.length > 0 };\n\tconst remaining = maximum - current.length;\n\treturn { value: Buffer.concat([current, chunk.subarray(0, remaining)]), truncated: chunk.length > remaining };\n}\nfunction exitTwoBlocks(input: HookInput): boolean {\n\treturn (\n\t\tinput.hook_event_name === \"PreToolUse\" ||\n\t\tinput.hook_event_name === \"UserPromptSubmit\" ||\n\t\tinput.hook_event_name === \"Stop\" ||\n\t\tinput.hook_event_name === \"PreCompact\"\n\t);\n}\nfunction structuredBlockingReason(output: HookOutputClassification, input: HookInput): string | undefined {\n\tif (output.kind !== \"json\") return undefined;\n\tif (output.value.continue === false && typeof output.value.stopReason === \"string\") return output.value.stopReason;\n\tif (input.hook_event_name === \"PreToolUse\") {\n\t\tconst specific = output.value.hookSpecificOutput;\n\t\tif (\n\t\t\tspecific?.hookEventName === input.hook_event_name &&\n\t\t\tspecific.permissionDecision === \"deny\" &&\n\t\t\ttypeof specific.permissionDecisionReason === \"string\"\n\t\t) {\n\t\t\treturn specific.permissionDecisionReason;\n\t\t}\n\t}\n\tif (output.value.decision === \"block\" && typeof output.value.reason === \"string\") return output.value.reason;\n\treturn undefined;\n}\nfunction diagnostic(hook: LoadedHookHandler, code: HookDiagnosticCode, message: string): HookDiagnostic {\n\treturn { level: \"warning\", code, message, source: hook.source, event: hook.event };\n}\nfunction resultBase(\n\thook: LoadedHookHandler,\n\tstarted: number,\n\tpartial: Partial<HookExecutionResult>,\n): HookExecutionResult {\n\treturn {\n\t\thook,\n\t\tstatus: \"error\",\n\t\texitCode: null,\n\t\tstdout: \"\",\n\t\tstderr: \"\",\n\t\tstdoutTruncated: false,\n\t\tstderrTruncated: false,\n\t\toutput: { kind: \"empty\" },\n\t\tblocking: false,\n\t\tdurationMs: performance.now() - started,\n\t\t...partial,\n\t};\n}\n\nfunction completedCommandStatus(state: CompletedCommandState): HookExecutionStatus {\n\tif (state.outputLimitExceeded) return \"error\";\n\tif (state.timedOut) return \"timeout\";\n\tif (state.cancelled) return \"cancelled\";\n\treturn \"completed\";\n}\n\nfunction completedCommandDiagnostic(\n\thook: LoadedHookHandler,\n\tstate: CompletedCommandState,\n\toutput: HookOutputClassification,\n): HookDiagnostic | undefined {\n\tif (state.outputLimitExceeded) {\n\t\treturn diagnostic(hook, \"execution\", \"Hook output exceeded the execution limit\");\n\t}\n\tif (output.kind !== \"text\" || !output.malformedJson) return undefined;\n\treturn diagnostic(hook, \"malformed-output\", \"Hook stdout looked like JSON but was malformed; output was ignored\");\n}\n\nfunction completedCommandResult(\n\thook: LoadedHookHandler,\n\tstarted: number,\n\tinput: HookInput,\n\texitCode: number | null,\n\tstate: CompletedCommandState,\n): HookExecutionResult {\n\tconst stdout = state.stdout.toString(\"utf8\");\n\tconst stderr = state.stderr.toString(\"utf8\");\n\tconst output = state.outputLimitExceeded ? { kind: \"empty\" as const } : classifyHookOutput(stdout);\n\tconst outputDiagnostic = completedCommandDiagnostic(hook, state, output);\n\tconst blocking =\n\t\t!state.timedOut && !state.cancelled && !state.outputLimitExceeded && exitCode === 2 && exitTwoBlocks(input);\n\treturn resultBase(hook, started, {\n\t\tstatus: completedCommandStatus(state),\n\t\texitCode,\n\t\tstdout,\n\t\tstderr,\n\t\tstdoutTruncated: state.stdoutTruncated,\n\t\tstderrTruncated: state.stderrTruncated,\n\t\toutput,\n\t\tdiagnostic: outputDiagnostic,\n\t\tblocking,\n\t\t...(blocking\n\t\t\t? { blockingReason: structuredBlockingReason(output, input) ?? (stderr.trim() || \"Hook blocked the action\") }\n\t\t\t: {}),\n\t});\n}\n\nfunction shellQuote(value: string): string {\n\treturn `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction projectHookUsesWorkspaceBackend(hook: LoadedHookHandler, options: HookRunOptions): boolean {\n\tif (hook.source.kind !== \"project\" && hook.source.kind !== \"local\") return false;\n\treturn options.toolOperations?.getBackendInfo?.()?.type !== \"local\";\n}\n\nconst WORKSPACE_HOOK_RUNNER = String.raw`\nconst { spawn } = require(\"node:child_process\");\nconst spec = JSON.parse(Buffer.from(process.argv[1], \"base64\").toString(\"utf8\"));\nconst env = { ...process.env };\nfor (const name of Object.keys(env)) {\n if (name.startsWith(\"OTEL_\") || /^(?:GRIP|PI)_.*(?:TOKEN|CREDENTIAL|API_KEY|SECRET|PASSWORD)/i.test(name)) delete env[name];\n}\nconst frame = (stream, data) => process.stdout.write(\"GRIPHOOK1 \" + stream + \" \" + Buffer.from(data).toString(\"base64\") + \"\\n\");\nlet failed = false;\nconst child = spawn(spec.file, spec.args, { cwd: spec.cwd, env, stdio: [\"pipe\", \"pipe\", \"pipe\"], windowsHide: true });\nchild.stdout.on(\"data\", (data) => frame(\"stdout\", data));\nchild.stderr.on(\"data\", (data) => frame(\"stderr\", data));\nchild.on(\"error\", (error) => { failed = true; frame(\"stderr\", Buffer.from(String(error))); process.exitCode = 127; });\nchild.on(\"close\", (code) => { if (!failed) process.exitCode = code === null ? 1 : code; });\nchild.stdin.on(\"error\", () => {});\nchild.stdin.end(Buffer.from(spec.stdinBase64, \"base64\"));\n`;\n\ninterface WorkspaceHookPreparation {\n\tok: boolean;\n\tcommand?: string;\n\tinput: HookInput;\n}\n\ninterface WorkspaceHookOutputState {\n\tmaximum: number;\n\tstdout: Buffer;\n\tstderr: Buffer;\n\tstdoutTruncated: boolean;\n\tstderrTruncated: boolean;\n\tpending: string;\n\toutputLimitExceeded: boolean;\n\toutputController: AbortController;\n}\n\nfunction prepareWorkspaceHook(\n\thandler: CommandHookHandler,\n\tinput: HookInput,\n\tcwd: string,\n\tpathFlavor: PortablePathFlavor,\n): WorkspaceHookPreparation {\n\tconst workspaceInput = { ...input, cwd };\n\tconst stdin = Buffer.from(JSON.stringify(workspaceInput));\n\tif (stdin.byteLength > 256 * 1024) return { ok: false, input: workspaceInput };\n\tlet file = handler.command;\n\tlet args = handler.args ?? [];\n\tif (handler.args === undefined) {\n\t\tif (handler.shell === \"powershell\" || (handler.shell === undefined && pathFlavor === \"windows\")) {\n\t\t\tfile = pathFlavor === \"windows\" ? \"powershell.exe\" : \"pwsh\";\n\t\t\targs = [\"-NoProfile\", \"-Command\", handler.command];\n\t\t} else {\n\t\t\tfile = handler.shell === \"bash\" ? \"bash\" : \"/bin/sh\";\n\t\t\targs = [\"-c\", handler.command];\n\t\t}\n\t}\n\tconst spec = Buffer.from(JSON.stringify({ file, args, cwd, stdinBase64: stdin.toString(\"base64\") })).toString(\n\t\t\"base64\",\n\t);\n\treturn {\n\t\tok: true,\n\t\tcommand: `node -e ${shellQuote(WORKSPACE_HOOK_RUNNER)} ${shellQuote(spec)}`,\n\t\tinput: workspaceInput,\n\t};\n}\n\nfunction createWorkspaceHookOutputState(maximum: number): WorkspaceHookOutputState {\n\treturn {\n\t\tmaximum,\n\t\tstdout: Buffer.alloc(0),\n\t\tstderr: Buffer.alloc(0),\n\t\tstdoutTruncated: false,\n\t\tstderrTruncated: false,\n\t\tpending: \"\",\n\t\toutputLimitExceeded: false,\n\t\toutputController: new AbortController(),\n\t};\n}\n\nfunction exceedWorkspaceHookOutputLimit(state: WorkspaceHookOutputState): void {\n\tif (state.outputLimitExceeded) return;\n\tstate.outputLimitExceeded = true;\n\tstate.outputController.abort();\n}\n\nfunction consumeWorkspaceHookLine(state: WorkspaceHookOutputState, line: string): void {\n\tconst match = /^GRIPHOOK1 (stdout|stderr) ([A-Za-z0-9+/]*={0,2})$/.exec(line);\n\tif (!match) {\n\t\tconst next = appendBounded(state.stderr, Buffer.from(`${line}\\n`), state.maximum);\n\t\tstate.stderr = next.value;\n\t\tstate.stderrTruncated ||= next.truncated;\n\t\tif (next.truncated) exceedWorkspaceHookOutputLimit(state);\n\t\treturn;\n\t}\n\tconst chunk = Buffer.from(match[2], \"base64\");\n\tif (match[1] === \"stdout\") {\n\t\tconst next = appendBounded(state.stdout, chunk, state.maximum);\n\t\tstate.stdout = next.value;\n\t\tstate.stdoutTruncated ||= next.truncated;\n\t} else {\n\t\tconst next = appendBounded(state.stderr, chunk, state.maximum);\n\t\tstate.stderr = next.value;\n\t\tstate.stderrTruncated ||= next.truncated;\n\t}\n\tif (state.stdoutTruncated || state.stderrTruncated) exceedWorkspaceHookOutputLimit(state);\n}\n\nfunction consumeWorkspaceHookData(state: WorkspaceHookOutputState, data: Buffer): void {\n\tif (state.outputLimitExceeded) return;\n\tstate.pending += data.toString(\"utf8\");\n\tconst maximumFrameChars = Math.ceil((state.maximum * 4) / 3) + 1024;\n\tif (state.pending.length > maximumFrameChars) {\n\t\tstate.pending = state.pending.slice(0, maximumFrameChars);\n\t\tstate.stderrTruncated = true;\n\t\texceedWorkspaceHookOutputLimit(state);\n\t\treturn;\n\t}\n\tconst lines = state.pending.split(\"\\n\");\n\tstate.pending = lines.pop() ?? \"\";\n\tfor (const line of lines) consumeWorkspaceHookLine(state, line.replace(/\\r$/, \"\"));\n}\n\nfunction completeWorkspaceHookOutput(state: WorkspaceHookOutputState): void {\n\tif (state.pending) consumeWorkspaceHookLine(state, state.pending);\n}\n\nfunction completedWorkspaceHookResult(\n\thook: LoadedHookHandler,\n\tstarted: number,\n\tinput: HookInput,\n\tstate: WorkspaceHookOutputState,\n\texitCode: number | null,\n): HookExecutionResult {\n\tconst stdout = state.stdout.toString(\"utf8\");\n\tconst stderr = state.stderr.toString(\"utf8\");\n\tconst output = state.outputLimitExceeded ? { kind: \"empty\" as const } : classifyHookOutput(stdout);\n\tlet outputDiagnostic: HookDiagnostic | undefined;\n\tif (output.kind === \"text\" && output.malformedJson) {\n\t\toutputDiagnostic = diagnostic(\n\t\t\thook,\n\t\t\t\"malformed-output\",\n\t\t\t\"Hook stdout looked like JSON but was malformed; output was ignored\",\n\t\t);\n\t} else if (state.outputLimitExceeded) {\n\t\toutputDiagnostic = diagnostic(hook, \"execution\", \"Project hook output exceeded the workspace execution limit\");\n\t}\n\tconst blocking = !state.outputLimitExceeded && exitCode === 2 && exitTwoBlocks(input);\n\treturn resultBase(hook, started, {\n\t\tstatus: state.outputLimitExceeded ? \"error\" : \"completed\",\n\t\texitCode,\n\t\tstdout,\n\t\tstderr,\n\t\tstdoutTruncated: state.stdoutTruncated,\n\t\tstderrTruncated: state.stderrTruncated,\n\t\toutput,\n\t\tdiagnostic: outputDiagnostic,\n\t\tblocking,\n\t\t...(blocking\n\t\t\t? { blockingReason: structuredBlockingReason(output, input) ?? (stderr.trim() || \"Hook blocked the action\") }\n\t\t\t: {}),\n\t});\n}\n\nfunction failedWorkspaceHookResult(\n\thook: LoadedHookHandler,\n\tstarted: number,\n\toptions: HookRunOptions,\n\tstate: WorkspaceHookOutputState,\n\terror: unknown,\n): HookExecutionResult {\n\tconst cancelled = !state.outputLimitExceeded && options.signal?.aborted === true;\n\treturn resultBase(hook, started, {\n\t\tstatus: cancelled ? \"cancelled\" : \"error\",\n\t\tstdout: state.stdout.toString(\"utf8\"),\n\t\tstderr: state.stderr.toString(\"utf8\"),\n\t\tstdoutTruncated: state.stdoutTruncated,\n\t\tstderrTruncated: state.stderrTruncated,\n\t\tdiagnostic: state.outputLimitExceeded\n\t\t\t? diagnostic(hook, \"execution\", \"Project hook output exceeded the workspace execution limit\")\n\t\t\t: cancelled\n\t\t\t\t? undefined\n\t\t\t\t: diagnostic(hook, \"execution\", `Workspace project hook failed: ${String(error)}`),\n\t});\n}\nasync function executeWorkspaceCommand(\n\thook: LoadedHookHandler,\n\thandler: CommandHookHandler,\n\tinput: HookInput,\n\toptions: HookRunOptions,\n): Promise<HookExecutionResult> {\n\tconst started = performance.now();\n\tconst operations = options.toolOperations;\n\tconst backend = operations?.getBackendInfo?.();\n\tif (!operations || !backend || backend.type === \"local\" || (backend.type === \"remote\" && !backend.configured)) {\n\t\treturn resultBase(hook, started, {\n\t\t\tdiagnostic: diagnostic(\n\t\t\t\thook,\n\t\t\t\t\"policy\",\n\t\t\t\t\"Project hook was not executed because the workspace backend is unavailable\",\n\t\t\t),\n\t\t});\n\t}\n\tconst pathFlavor = backend.type === \"remote\" && backend.configured ? backend.workspace.pathFlavor : \"posix\";\n\tconst preparation = prepareWorkspaceHook(handler, input, backend.cwd, pathFlavor);\n\tif (!preparation.ok || !preparation.command) {\n\t\treturn resultBase(hook, started, {\n\t\t\tdiagnostic: diagnostic(hook, \"policy\", \"Project hook input exceeds the workspace execution limit\"),\n\t\t});\n\t}\n\tconst state = createWorkspaceHookOutputState(options.maxOutputBytes ?? DEFAULT_MAX_HOOK_OUTPUT_BYTES);\n\tconst signals = [options.signal, state.outputController.signal].filter(\n\t\t(signal): signal is AbortSignal => signal !== undefined,\n\t);\n\tconst signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);\n\ttry {\n\t\tconst result = await operations.exec(preparation.command, {\n\t\t\tcwd: backend.cwd,\n\t\t\tonData: (data) => consumeWorkspaceHookData(state, data),\n\t\t\tsignal,\n\t\t\ttimeout: hookTimeoutSeconds(handler, preparation.input, options),\n\t\t});\n\t\tcompleteWorkspaceHookOutput(state);\n\t\treturn completedWorkspaceHookResult(hook, started, preparation.input, state, result.exitCode);\n\t} catch (error) {\n\t\treturn failedWorkspaceHookResult(hook, started, options, state, error);\n\t}\n}\n\nasync function executeCommand(\n\thook: LoadedHookHandler,\n\thandler: CommandHookHandler,\n\tinput: HookInput,\n\toptions: HookRunOptions,\n): Promise<HookExecutionResult> {\n\tif (projectHookUsesWorkspaceBackend(hook, options)) return executeWorkspaceCommand(hook, handler, input, options);\n\tconst started = performance.now();\n\tconst timeoutMs = hookTimeoutSeconds(handler, input, options) * 1000;\n\tconst maximum = options.maxOutputBytes ?? DEFAULT_MAX_HOOK_OUTPUT_BYTES;\n\tconst useExec = handler.args !== undefined;\n\tlet command = handler.command;\n\tlet args = handler.args ?? [];\n\tif (!useExec) {\n\t\tif (handler.shell === \"powershell\") {\n\t\t\tcommand = process.platform === \"win32\" ? \"powershell.exe\" : \"pwsh\";\n\t\t\targs = [\"-NoProfile\", \"-Command\", handler.command];\n\t\t} else if (handler.shell === \"bash\") {\n\t\t\tcommand = \"bash\";\n\t\t\targs = [\"-c\", handler.command];\n\t\t} else if (process.platform === \"win32\") {\n\t\t\tcommand = \"powershell.exe\";\n\t\t\targs = [\"-NoProfile\", \"-Command\", handler.command];\n\t\t} else {\n\t\t\tcommand = \"/bin/sh\";\n\t\t\targs = [\"-c\", handler.command];\n\t\t}\n\t}\n\treturn await new Promise((resolve) => {\n\t\tlet child: ChildProcessWithoutNullStreams;\n\t\ttry {\n\t\t\tchild = spawn(command, args, {\n\t\t\t\tcwd: input.cwd,\n\t\t\t\tenv: sanitizedHookEnvironment(options.env),\n\t\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tresolve(resultBase(hook, started, { diagnostic: diagnostic(hook, \"execution\", String(error)) }));\n\t\t\treturn;\n\t\t}\n\t\tlet stdout: Buffer = Buffer.alloc(0);\n\t\tlet stderr: Buffer = Buffer.alloc(0);\n\t\tlet stdoutTruncated = false;\n\t\tlet stderrTruncated = false;\n\t\tlet outputLimitExceeded = false;\n\t\tlet settled = false;\n\t\tlet timedOut = false;\n\t\tlet cancelled = false;\n\t\tconst platform = options.platform ?? process.platform;\n\t\tlet windowsTerminationStarted = false;\n\t\tconst terminateWindowsTree = (pid: number) => {\n\t\t\tif (windowsTerminationStarted) return;\n\t\t\twindowsTerminationStarted = true;\n\t\t\tconst fallback = () => {\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(\"SIGKILL\");\n\t\t\t};\n\t\t\tif (options.terminateWindowsProcessTree) {\n\t\t\t\t// The abstraction is invoked before any direct-child fallback, matching taskkill ordering.\n\t\t\t\tif (!options.terminateWindowsProcessTree(pid)) fallback();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst killer = spawn(\"taskkill\", [\"/PID\", String(pid), \"/T\", \"/F\"], {\n\t\t\t\t\tstdio: \"ignore\",\n\t\t\t\t\twindowsHide: true,\n\t\t\t\t});\n\t\t\t\tconst bound = setTimeout(() => {\n\t\t\t\t\tkiller.kill();\n\t\t\t\t\tfallback();\n\t\t\t\t}, 1000);\n\t\t\t\tbound.unref();\n\t\t\t\tkiller.once(\"close\", (code) => {\n\t\t\t\t\tclearTimeout(bound);\n\t\t\t\t\tif (code !== 0) fallback();\n\t\t\t\t});\n\t\t\t\tkiller.once(\"error\", () => {\n\t\t\t\t\tclearTimeout(bound);\n\t\t\t\t\tfallback();\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tfallback();\n\t\t\t}\n\t\t};\n\t\tconst terminate = () => {\n\t\t\tif (child.pid && platform === \"win32\") {\n\t\t\t\t// taskkill /T /F gets a bounded opportunity before direct-child fallback.\n\t\t\t\tterminateWindowsTree(child.pid);\n\t\t\t} else if (child.pid) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(-child.pid, \"SIGTERM\");\n\t\t\t\t} catch {\n\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t}\n\t\t\t} else child.kill(\"SIGTERM\");\n\t\t\tsetTimeout(() => {\n\t\t\t\tforceTerminateChildProcess(child, platform, terminateWindowsTree);\n\t\t\t}, 250).unref();\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tcancelled = true;\n\t\t\tterminate();\n\t\t};\n\t\tif (options.signal?.aborted) onAbort();\n\t\telse options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tterminate();\n\t\t}, timeoutMs);\n\t\tchild.stdout.on(\"data\", (data: Buffer) => {\n\t\t\tconst next = appendBounded(stdout, data, maximum);\n\t\t\tstdout = next.value;\n\t\t\tstdoutTruncated ||= next.truncated;\n\t\t\tif (next.truncated && !outputLimitExceeded) {\n\t\t\t\toutputLimitExceeded = true;\n\t\t\t\tterminate();\n\t\t\t}\n\t\t});\n\t\tchild.stderr.on(\"data\", (data: Buffer) => {\n\t\t\tconst next = appendBounded(stderr, data, maximum);\n\t\t\tstderr = next.value;\n\t\t\tstderrTruncated ||= next.truncated;\n\t\t\tif (next.truncated && !outputLimitExceeded) {\n\t\t\t\toutputLimitExceeded = true;\n\t\t\t\tterminate();\n\t\t\t}\n\t\t});\n\t\tchild.on(\"error\", (error) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve(\n\t\t\t\tresultBase(hook, started, {\n\t\t\t\t\tstdout: stdout.toString(\"utf8\"),\n\t\t\t\t\tstderr: stderr.toString(\"utf8\"),\n\t\t\t\t\tstdoutTruncated,\n\t\t\t\t\tstderrTruncated,\n\t\t\t\t\tdiagnostic: diagnostic(hook, \"execution\", String(error)),\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t\tchild.on(\"close\", (code) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve(\n\t\t\t\tcompletedCommandResult(hook, started, input, code, {\n\t\t\t\t\tstdout,\n\t\t\t\t\tstderr,\n\t\t\t\t\tstdoutTruncated,\n\t\t\t\t\tstderrTruncated,\n\t\t\t\t\toutputLimitExceeded,\n\t\t\t\t\ttimedOut,\n\t\t\t\t\tcancelled,\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t\tchild.stdin.on(\"error\", () => undefined);\n\t\tchild.stdin.end(JSON.stringify(input));\n\t});\n}\nfunction interpolateHeader(value: string, allowed: Set<string>, env: NodeJS.ProcessEnv): string {\n\treturn value.replace(\n\t\t/\\$(?:\\{([A-Za-z_][A-Za-z0-9_]*)\\}|([A-Za-z_][A-Za-z0-9_]*))/g,\n\t\t(_match, braced: string | undefined, bare: string | undefined) => {\n\t\t\tconst name = braced ?? bare ?? \"\";\n\t\t\treturn allowed.has(name) ? (env[name] ?? \"\") : \"\";\n\t\t},\n\t);\n}\nfunction httpHookTransportAllowed(value: string): boolean {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\treturn false;\n\t}\n\tif (url.protocol === \"https:\") return true;\n\tif (url.protocol !== \"http:\") return false;\n\tconst hostname = url.hostname.replace(/^\\[|\\]$/g, \"\").toLowerCase();\n\treturn (\n\t\thostname === \"localhost\" ||\n\t\thostname === \"::1\" ||\n\t\t/^127(?:\\.[0-9]{1,3}){3}$/.test(hostname) ||\n\t\t/^::ffff:127(?:\\.[0-9]{1,3}){3}$/.test(hostname)\n\t);\n}\n\ninterface HttpHookResponseBody {\n\tstdout: string;\n\ttruncated: boolean;\n}\n\nfunction createHttpHookHeaders(\n\thook: LoadedHookHandler,\n\thandler: HttpHookHandler,\n\toptions: HookRunOptions,\n\tenv: NodeJS.ProcessEnv,\n): Record<string, string> {\n\tconst settingsAllowed = new Set(hook.httpHookAllowedEnvVars ?? handler.allowedEnvVars ?? []);\n\tconst hostAllowed = options.httpHookAllowedEnvVars ? new Set(options.httpHookAllowedEnvVars) : undefined;\n\tconst allowed = new Set([...settingsAllowed].filter((name) => !hostAllowed || hostAllowed.has(name)));\n\tconst headers: Record<string, string> = { \"content-type\": \"application/json\" };\n\tfor (const [key, value] of Object.entries(handler.headers ?? {})) {\n\t\theaders[key] = interpolateHeader(value, allowed, env);\n\t}\n\treturn headers;\n}\n\nasync function readHttpHookResponseBody(response: Response, maximum: number): Promise<HttpHookResponseBody> {\n\tlet raw: Buffer = Buffer.alloc(0);\n\tlet truncated = false;\n\tif (!response.body) return { stdout: \"\", truncated };\n\n\tconst reader = response.body.getReader();\n\ttry {\n\t\twhile (true) {\n\t\t\tconst next = await reader.read();\n\t\t\tif (next.done) break;\n\t\t\tconst bounded = appendBounded(raw, Buffer.from(next.value), maximum);\n\t\t\traw = bounded.value;\n\t\t\ttruncated ||= bounded.truncated;\n\t\t\tif (!truncated) continue;\n\t\t\tawait reader.cancel();\n\t\t\tbreak;\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\treturn { stdout: raw.toString(\"utf8\"), truncated };\n}\n\nfunction completedHttpHookResult(\n\thook: LoadedHookHandler,\n\tstarted: number,\n\tresponse: Response,\n\tbody: HttpHookResponseBody,\n): HookExecutionResult {\n\tlet output: HookOutputClassification = { kind: \"empty\" };\n\tlet responseDiagnostic: HookDiagnostic | undefined;\n\tif (body.truncated) {\n\t\tresponseDiagnostic = diagnostic(hook, \"execution\", \"HTTP hook output exceeded the execution limit\");\n\t} else if (response.status >= 300 && response.status < 400) {\n\t\tresponseDiagnostic = diagnostic(hook, \"policy\", \"HTTP hook redirects are rejected\");\n\t} else if (!response.ok) {\n\t\tresponseDiagnostic = diagnostic(hook, \"execution\", `HTTP hook returned ${response.status}`);\n\t} else {\n\t\tconst classified = classifyHookOutput(body.stdout);\n\t\tif (classified.kind === \"json\" || classified.kind === \"empty\") output = classified;\n\t\telse {\n\t\t\tresponseDiagnostic = diagnostic(\n\t\t\t\thook,\n\t\t\t\t\"malformed-output\",\n\t\t\t\t\"HTTP hook 2xx response was not structured JSON; response was ignored\",\n\t\t\t);\n\t\t}\n\t}\n\treturn resultBase(hook, started, {\n\t\tstatus: body.truncated ? \"error\" : \"completed\",\n\t\texitCode: response.ok && !body.truncated ? 0 : 1,\n\t\tstdout: body.stdout,\n\t\tstderr: \"\",\n\t\tstdoutTruncated: body.truncated,\n\t\toutput,\n\t\tdiagnostic: responseDiagnostic,\n\t});\n}\n\nfunction failedHttpHookResult(\n\thook: LoadedHookHandler,\n\tstarted: number,\n\ttimedOut: boolean,\n\tcancelled: boolean,\n\terror: unknown,\n): HookExecutionResult {\n\treturn resultBase(hook, started, {\n\t\tstatus: timedOut ? \"timeout\" : cancelled ? \"cancelled\" : \"error\",\n\t\tdiagnostic:\n\t\t\ttimedOut || cancelled ? undefined : diagnostic(hook, \"execution\", `HTTP hook failed: ${String(error)}`),\n\t});\n}\n\nasync function executeHttp(\n\thook: LoadedHookHandler,\n\thandler: HttpHookHandler,\n\tinput: HookInput,\n\toptions: HookRunOptions,\n): Promise<HookExecutionResult> {\n\tconst started = performance.now();\n\tif (!httpHookTransportAllowed(handler.url)) {\n\t\treturn resultBase(hook, started, {\n\t\t\tdiagnostic: diagnostic(hook, \"policy\", `HTTP hook requires HTTPS unless it targets loopback: ${handler.url}`),\n\t\t});\n\t}\n\tif (projectHookUsesWorkspaceBackend(hook, options)) {\n\t\treturn resultBase(hook, started, {\n\t\t\tdiagnostic: diagnostic(\n\t\t\t\thook,\n\t\t\t\t\"policy\",\n\t\t\t\t\"Project HTTP hooks are disabled on non-local workspace backends to prevent host-network escape\",\n\t\t\t),\n\t\t});\n\t}\n\n\tconst controller = new AbortController();\n\tconst timeoutMs = hookTimeoutSeconds(handler, input, options) * 1000;\n\tlet timedOut = false;\n\tlet cancelled = false;\n\tconst onAbort = () => {\n\t\tcancelled = true;\n\t\tcontroller.abort();\n\t};\n\tif (options.signal?.aborted) onAbort();\n\telse options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\tconst timer = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\n\ttry {\n\t\tconst env = sanitizedHookEnvironment(options.env);\n\t\tif (options.allowedHttpHookUrls && !urlAllowed(handler.url, options.allowedHttpHookUrls)) {\n\t\t\treturn resultBase(hook, started, {\n\t\t\t\tdiagnostic: diagnostic(hook, \"policy\", `HTTP hook URL is blocked by the host: ${handler.url}`),\n\t\t\t});\n\t\t}\n\t\tconst headers = createHttpHookHeaders(hook, handler, options, env);\n\t\tconst response = await (options.fetch ?? globalThis.fetch)(handler.url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(input),\n\t\t\tsignal: controller.signal,\n\t\t\tredirect: \"error\",\n\t\t});\n\t\tconst body = await readHttpHookResponseBody(response, options.maxOutputBytes ?? DEFAULT_MAX_HOOK_OUTPUT_BYTES);\n\t\treturn completedHttpHookResult(hook, started, response, body);\n\t} catch (error) {\n\t\treturn failedHttpHookResult(hook, started, timedOut, cancelled, error);\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t}\n}\n\nfunction urlAllowed(url: string, allowlist: readonly string[]): boolean {\n\treturn allowlist.some((pattern) => {\n\t\tif (pattern === url) return true;\n\t\tconst expression = pattern\n\t\t\t.split(\"*\")\n\t\t\t.map((part) => part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n\t\t\t.join(\".*\");\n\t\treturn new RegExp(`^${expression}$`).test(url);\n\t});\n}\n\nexport async function executeHook(\n\thook: LoadedHookHandler,\n\tinput: HookInput,\n\toptions: HookRunOptions = {},\n): Promise<HookExecutionResult> {\n\tconst started = performance.now();\n\tif (options.signal?.aborted) return resultBase(hook, started, { status: \"cancelled\" });\n\tif (hook.handler.type === \"prompt\" || hook.handler.type === \"agent\" || hook.handler.type === \"mcp_tool\") {\n\t\treturn resultBase(hook, started, {\n\t\t\tstatus: \"unsupported\",\n\t\t\tdiagnostic: diagnostic(hook, \"unsupported-handler\", `${hook.handler.type} handlers are unsupported`),\n\t\t});\n\t}\n\tif (hook.handler.type === \"command\") return executeCommand(hook, hook.handler, input, options);\n\tif (hook.handler.type === \"http\") return executeHttp(hook, hook.handler, input, options);\n\treturn resultBase(hook, started, { status: \"unsupported\" });\n}\n\nexport async function executeMatchingHooks(\n\thooks: readonly LoadedHookHandler[],\n\tinput: HookInput,\n\toptions: HookRunOptions = {},\n): Promise<HookExecutionResult[]> {\n\tconst matching = hooks.filter(\n\t\t(hook) =>\n\t\t\thook.event === input.hook_event_name &&\n\t\t\tmatchesHookInput(hook.matcher, input).matches &&\n\t\t\tmatchesHookIf(hook.handler.if, input).matches,\n\t);\n\tconst runOptions =\n\t\tinput.hook_event_name === \"SessionEnd\"\n\t\t\t? {\n\t\t\t\t\t...options,\n\t\t\t\t\ttimeoutSeconds: Math.min(\n\t\t\t\t\t\tMAX_SESSION_END_HOOK_TIMEOUT_SECONDS,\n\t\t\t\t\t\tMath.max(\n\t\t\t\t\t\t\tDEFAULT_SESSION_END_HOOK_TIMEOUT_SECONDS,\n\t\t\t\t\t\t\t...matching.map((hook) => hook.handler.timeout ?? DEFAULT_SESSION_END_HOOK_TIMEOUT_SECONDS),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: options;\n\treturn Promise.all(matching.map((hook) => executeHook(hook, input, runOptions)));\n}\n"]}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAIX,mBAAmB,EAGnB,SAAS,EACT,wBAAwB,EACxB,cAAc,EAGd,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,wCAAwC,KAAK,CAAC;AAC3D,eAAO,MAAM,wCAAwC,MAAM,CAAC;AAC5D,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAmDzD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAS3E;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAIlE;AAOD,wBAAgB,wBAAwB,CAAC,MAAM,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,UAAU,CAQnG;AAurBD,wBAAsB,WAAW,CAChC,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAY9B;AAED,wBAAsB,oBAAoB,CACzC,KAAK,EAAE,SAAS,iBAAiB,EAAE,EACnC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAqBhC"}