subagent-cli 0.3.0 → 0.3.1

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 (2177) hide show
  1. package/dist/sa +0 -0
  2. package/package.json +2 -8
  3. package/_entry.ts +0 -2
  4. package/bunfig.toml +0 -2
  5. package/src/QueryEngine.ts +0 -1295
  6. package/src/Task.ts +0 -125
  7. package/src/Tool.ts +0 -792
  8. package/src/_stubs/bun-bundle.ts +0 -6
  9. package/src/assistant/AssistantSessionChooser.ts +0 -2
  10. package/src/assistant/gate.ts +0 -2
  11. package/src/assistant/index.ts +0 -2
  12. package/src/assistant/sessionDiscovery.ts +0 -1
  13. package/src/assistant/sessionHistory.ts +0 -87
  14. package/src/bootstrap/state.ts +0 -1762
  15. package/src/bridge/bridgeApi.ts +0 -539
  16. package/src/bridge/bridgeConfig.ts +0 -48
  17. package/src/bridge/bridgeDebug.ts +0 -135
  18. package/src/bridge/bridgeEnabled.ts +0 -202
  19. package/src/bridge/bridgeMain.ts +0 -2999
  20. package/src/bridge/bridgeMessaging.ts +0 -461
  21. package/src/bridge/bridgePermissionCallbacks.ts +0 -43
  22. package/src/bridge/bridgePointer.ts +0 -210
  23. package/src/bridge/bridgeStatusUtil.ts +0 -163
  24. package/src/bridge/bridgeUI.ts +0 -530
  25. package/src/bridge/capacityWake.ts +0 -56
  26. package/src/bridge/codeSessionApi.ts +0 -168
  27. package/src/bridge/createSession.ts +0 -384
  28. package/src/bridge/debugUtils.ts +0 -141
  29. package/src/bridge/envLessBridgeConfig.ts +0 -165
  30. package/src/bridge/flushGate.ts +0 -71
  31. package/src/bridge/inboundAttachments.ts +0 -175
  32. package/src/bridge/inboundMessages.ts +0 -80
  33. package/src/bridge/initReplBridge.ts +0 -569
  34. package/src/bridge/jwtUtils.ts +0 -256
  35. package/src/bridge/peerSessions.ts +0 -2
  36. package/src/bridge/pollConfig.ts +0 -110
  37. package/src/bridge/pollConfigDefaults.ts +0 -82
  38. package/src/bridge/remoteBridgeCore.ts +0 -1008
  39. package/src/bridge/replBridge.ts +0 -2406
  40. package/src/bridge/replBridgeHandle.ts +0 -36
  41. package/src/bridge/replBridgeTransport.ts +0 -370
  42. package/src/bridge/sessionIdCompat.ts +0 -57
  43. package/src/bridge/sessionRunner.ts +0 -550
  44. package/src/bridge/trustedDevice.ts +0 -210
  45. package/src/bridge/types.ts +0 -262
  46. package/src/bridge/webhookSanitizer.ts +0 -2
  47. package/src/bridge/workSecret.ts +0 -127
  48. package/src/buddy/CompanionSprite.tsx +0 -371
  49. package/src/buddy/companion.ts +0 -133
  50. package/src/buddy/prompt.ts +0 -36
  51. package/src/buddy/sprites.ts +0 -514
  52. package/src/buddy/types.ts +0 -148
  53. package/src/buddy/useBuddyNotification.tsx +0 -98
  54. package/src/cli/bg.ts +0 -2
  55. package/src/cli/exit.ts +0 -31
  56. package/src/cli/handlers/agents.ts +0 -70
  57. package/src/cli/handlers/ant.ts +0 -2
  58. package/src/cli/handlers/auth.ts +0 -330
  59. package/src/cli/handlers/autoMode.ts +0 -170
  60. package/src/cli/handlers/mcp.tsx +0 -362
  61. package/src/cli/handlers/plugins.ts +0 -878
  62. package/src/cli/handlers/templateJobs.ts +0 -2
  63. package/src/cli/handlers/util.tsx +0 -110
  64. package/src/cli/ndjsonSafeStringify.ts +0 -32
  65. package/src/cli/print.ts +0 -5594
  66. package/src/cli/remoteIO.ts +0 -255
  67. package/src/cli/rollback.ts +0 -3
  68. package/src/cli/structuredIO.ts +0 -859
  69. package/src/cli/transports/HybridTransport.ts +0 -282
  70. package/src/cli/transports/SSETransport.ts +0 -711
  71. package/src/cli/transports/SerialBatchEventUploader.ts +0 -275
  72. package/src/cli/transports/Transport.ts +0 -1
  73. package/src/cli/transports/WebSocketTransport.ts +0 -800
  74. package/src/cli/transports/WorkerStateUploader.ts +0 -131
  75. package/src/cli/transports/ccrClient.ts +0 -998
  76. package/src/cli/transports/transportUtils.ts +0 -45
  77. package/src/cli/up.ts +0 -3
  78. package/src/cli/update.ts +0 -422
  79. package/src/commands/add-dir/add-dir.tsx +0 -126
  80. package/src/commands/add-dir/index.ts +0 -11
  81. package/src/commands/add-dir/validation.ts +0 -110
  82. package/src/commands/advisor.ts +0 -109
  83. package/src/commands/agents/agents.tsx +0 -12
  84. package/src/commands/agents/index.ts +0 -10
  85. package/src/commands/agents-platform/index.ts +0 -1
  86. package/src/commands/ant-trace/index.js +0 -1
  87. package/src/commands/assistant/assistant.ts +0 -2
  88. package/src/commands/assistant/index.ts +0 -1
  89. package/src/commands/autofix-pr/index.js +0 -1
  90. package/src/commands/backfill-sessions/index.js +0 -1
  91. package/src/commands/branch/branch.ts +0 -296
  92. package/src/commands/branch/index.ts +0 -14
  93. package/src/commands/break-cache/index.js +0 -1
  94. package/src/commands/bridge/bridge.tsx +0 -509
  95. package/src/commands/bridge/index.ts +0 -26
  96. package/src/commands/bridge-kick.ts +0 -200
  97. package/src/commands/brief.ts +0 -130
  98. package/src/commands/btw/btw.tsx +0 -243
  99. package/src/commands/btw/index.ts +0 -13
  100. package/src/commands/buddy/index.ts +0 -2
  101. package/src/commands/bughunter/index.js +0 -1
  102. package/src/commands/chrome/chrome.tsx +0 -285
  103. package/src/commands/chrome/index.ts +0 -13
  104. package/src/commands/clear/caches.ts +0 -144
  105. package/src/commands/clear/clear.ts +0 -7
  106. package/src/commands/clear/conversation.ts +0 -251
  107. package/src/commands/clear/index.ts +0 -19
  108. package/src/commands/color/color.ts +0 -93
  109. package/src/commands/color/index.ts +0 -16
  110. package/src/commands/commit-push-pr.ts +0 -158
  111. package/src/commands/commit.ts +0 -92
  112. package/src/commands/compact/compact.ts +0 -287
  113. package/src/commands/compact/index.ts +0 -15
  114. package/src/commands/config/config.tsx +0 -7
  115. package/src/commands/config/index.ts +0 -11
  116. package/src/commands/context/context-noninteractive.ts +0 -325
  117. package/src/commands/context/context.tsx +0 -64
  118. package/src/commands/context/index.ts +0 -24
  119. package/src/commands/copy/copy.tsx +0 -371
  120. package/src/commands/copy/index.ts +0 -15
  121. package/src/commands/cost/cost.ts +0 -24
  122. package/src/commands/cost/index.ts +0 -23
  123. package/src/commands/createMovedToPluginCommand.ts +0 -65
  124. package/src/commands/ctx_viz/index.js +0 -1
  125. package/src/commands/debug-tool-call/index.js +0 -1
  126. package/src/commands/desktop/desktop.tsx +0 -9
  127. package/src/commands/desktop/index.ts +0 -26
  128. package/src/commands/diff/diff.tsx +0 -9
  129. package/src/commands/diff/index.ts +0 -8
  130. package/src/commands/doctor/doctor.tsx +0 -7
  131. package/src/commands/doctor/index.ts +0 -12
  132. package/src/commands/effort/effort.tsx +0 -183
  133. package/src/commands/effort/index.ts +0 -13
  134. package/src/commands/env/index.js +0 -1
  135. package/src/commands/exit/exit.tsx +0 -33
  136. package/src/commands/exit/index.ts +0 -12
  137. package/src/commands/export/export.tsx +0 -91
  138. package/src/commands/export/index.ts +0 -11
  139. package/src/commands/extra-usage/extra-usage-core.ts +0 -118
  140. package/src/commands/extra-usage/extra-usage-noninteractive.ts +0 -16
  141. package/src/commands/extra-usage/extra-usage.tsx +0 -17
  142. package/src/commands/extra-usage/index.ts +0 -31
  143. package/src/commands/fast/fast.tsx +0 -269
  144. package/src/commands/fast/index.ts +0 -26
  145. package/src/commands/feedback/feedback.tsx +0 -25
  146. package/src/commands/feedback/index.ts +0 -26
  147. package/src/commands/files/files.ts +0 -19
  148. package/src/commands/files/index.ts +0 -12
  149. package/src/commands/force-snip.ts +0 -1
  150. package/src/commands/fork/index.ts +0 -2
  151. package/src/commands/good-claude/index.js +0 -1
  152. package/src/commands/heapdump/heapdump.ts +0 -17
  153. package/src/commands/heapdump/index.ts +0 -12
  154. package/src/commands/help/help.tsx +0 -11
  155. package/src/commands/help/index.ts +0 -10
  156. package/src/commands/hooks/hooks.tsx +0 -13
  157. package/src/commands/hooks/index.ts +0 -11
  158. package/src/commands/ide/ide.tsx +0 -646
  159. package/src/commands/ide/index.ts +0 -11
  160. package/src/commands/init-verifiers.ts +0 -262
  161. package/src/commands/init.ts +0 -256
  162. package/src/commands/insights.ts +0 -3200
  163. package/src/commands/install-github-app/ApiKeyStep.tsx +0 -231
  164. package/src/commands/install-github-app/CheckExistingSecretStep.tsx +0 -190
  165. package/src/commands/install-github-app/CheckGitHubStep.tsx +0 -15
  166. package/src/commands/install-github-app/ChooseRepoStep.tsx +0 -211
  167. package/src/commands/install-github-app/CreatingStep.tsx +0 -65
  168. package/src/commands/install-github-app/ErrorStep.tsx +0 -85
  169. package/src/commands/install-github-app/ExistingWorkflowStep.tsx +0 -103
  170. package/src/commands/install-github-app/InstallAppStep.tsx +0 -94
  171. package/src/commands/install-github-app/OAuthFlowStep.tsx +0 -276
  172. package/src/commands/install-github-app/SuccessStep.tsx +0 -96
  173. package/src/commands/install-github-app/WarningsStep.tsx +0 -73
  174. package/src/commands/install-github-app/index.ts +0 -13
  175. package/src/commands/install-github-app/install-github-app.tsx +0 -587
  176. package/src/commands/install-github-app/setupGitHubActions.ts +0 -325
  177. package/src/commands/install-github-app/types.ts +0 -3
  178. package/src/commands/install-slack-app/index.ts +0 -12
  179. package/src/commands/install-slack-app/install-slack-app.ts +0 -30
  180. package/src/commands/install.tsx +0 -300
  181. package/src/commands/issue/index.js +0 -1
  182. package/src/commands/keybindings/index.ts +0 -13
  183. package/src/commands/keybindings/keybindings.ts +0 -53
  184. package/src/commands/login/index.ts +0 -14
  185. package/src/commands/login/login.tsx +0 -104
  186. package/src/commands/logout/index.ts +0 -10
  187. package/src/commands/logout/logout.tsx +0 -82
  188. package/src/commands/mcp/addCommand.ts +0 -280
  189. package/src/commands/mcp/index.ts +0 -12
  190. package/src/commands/mcp/mcp.tsx +0 -85
  191. package/src/commands/mcp/xaaIdpCommand.ts +0 -266
  192. package/src/commands/memory/index.ts +0 -10
  193. package/src/commands/memory/memory.tsx +0 -90
  194. package/src/commands/mobile/index.ts +0 -11
  195. package/src/commands/mobile/mobile.tsx +0 -274
  196. package/src/commands/mock-limits/index.js +0 -1
  197. package/src/commands/model/index.ts +0 -16
  198. package/src/commands/model/model.tsx +0 -297
  199. package/src/commands/oauth-refresh/index.js +0 -1
  200. package/src/commands/onboarding/index.js +0 -1
  201. package/src/commands/output-style/index.ts +0 -11
  202. package/src/commands/output-style/output-style.tsx +0 -7
  203. package/src/commands/passes/index.ts +0 -22
  204. package/src/commands/passes/passes.tsx +0 -24
  205. package/src/commands/peers/index.ts +0 -2
  206. package/src/commands/perf-issue/index.js +0 -1
  207. package/src/commands/permissions/index.ts +0 -11
  208. package/src/commands/permissions/permissions.tsx +0 -10
  209. package/src/commands/plan/index.ts +0 -11
  210. package/src/commands/plan/plan.tsx +0 -122
  211. package/src/commands/plugin/AddMarketplace.tsx +0 -162
  212. package/src/commands/plugin/BrowseMarketplace.tsx +0 -802
  213. package/src/commands/plugin/DiscoverPlugins.tsx +0 -781
  214. package/src/commands/plugin/ManageMarketplaces.tsx +0 -838
  215. package/src/commands/plugin/ManagePlugins.tsx +0 -2215
  216. package/src/commands/plugin/PluginErrors.tsx +0 -124
  217. package/src/commands/plugin/PluginOptionsDialog.tsx +0 -357
  218. package/src/commands/plugin/PluginOptionsFlow.tsx +0 -135
  219. package/src/commands/plugin/PluginSettings.tsx +0 -1072
  220. package/src/commands/plugin/PluginTrustWarning.tsx +0 -32
  221. package/src/commands/plugin/UnifiedInstalledCell.tsx +0 -565
  222. package/src/commands/plugin/ValidatePlugin.tsx +0 -98
  223. package/src/commands/plugin/index.tsx +0 -11
  224. package/src/commands/plugin/parseArgs.ts +0 -103
  225. package/src/commands/plugin/plugin.tsx +0 -7
  226. package/src/commands/plugin/pluginDetailsHelpers.tsx +0 -117
  227. package/src/commands/plugin/types.ts +0 -2
  228. package/src/commands/plugin/unifiedTypes.ts +0 -4
  229. package/src/commands/plugin/usePagination.ts +0 -171
  230. package/src/commands/pr_comments/index.ts +0 -50
  231. package/src/commands/privacy-settings/index.ts +0 -14
  232. package/src/commands/privacy-settings/privacy-settings.tsx +0 -58
  233. package/src/commands/proactive.ts +0 -1
  234. package/src/commands/rate-limit-options/index.ts +0 -19
  235. package/src/commands/rate-limit-options/rate-limit-options.tsx +0 -210
  236. package/src/commands/release-notes/index.ts +0 -11
  237. package/src/commands/release-notes/release-notes.ts +0 -50
  238. package/src/commands/reload-plugins/index.ts +0 -18
  239. package/src/commands/reload-plugins/reload-plugins.ts +0 -61
  240. package/src/commands/remote-env/index.ts +0 -15
  241. package/src/commands/remote-env/remote-env.tsx +0 -7
  242. package/src/commands/remote-setup/api.ts +0 -182
  243. package/src/commands/remote-setup/index.ts +0 -20
  244. package/src/commands/remote-setup/remote-setup.tsx +0 -187
  245. package/src/commands/remoteControlServer/index.ts +0 -1
  246. package/src/commands/rename/generateSessionName.ts +0 -67
  247. package/src/commands/rename/index.ts +0 -12
  248. package/src/commands/rename/rename.ts +0 -87
  249. package/src/commands/reset-limits/index.js +0 -4
  250. package/src/commands/resume/index.ts +0 -12
  251. package/src/commands/resume/resume.tsx +0 -275
  252. package/src/commands/review/UltrareviewOverageDialog.tsx +0 -96
  253. package/src/commands/review/reviewRemote.ts +0 -316
  254. package/src/commands/review/ultrareviewCommand.tsx +0 -58
  255. package/src/commands/review/ultrareviewEnabled.ts +0 -14
  256. package/src/commands/review.ts +0 -57
  257. package/src/commands/rewind/index.ts +0 -13
  258. package/src/commands/rewind/rewind.ts +0 -13
  259. package/src/commands/sandbox-toggle/index.ts +0 -50
  260. package/src/commands/sandbox-toggle/sandbox-toggle.tsx +0 -83
  261. package/src/commands/security-review.ts +0 -243
  262. package/src/commands/session/index.ts +0 -16
  263. package/src/commands/session/session.tsx +0 -140
  264. package/src/commands/share/index.js +0 -1
  265. package/src/commands/skills/index.ts +0 -10
  266. package/src/commands/skills/skills.tsx +0 -8
  267. package/src/commands/stats/index.ts +0 -10
  268. package/src/commands/stats/stats.tsx +0 -7
  269. package/src/commands/status/index.ts +0 -12
  270. package/src/commands/status/status.tsx +0 -8
  271. package/src/commands/statusline.tsx +0 -24
  272. package/src/commands/stickers/index.ts +0 -11
  273. package/src/commands/stickers/stickers.ts +0 -16
  274. package/src/commands/subscribe-pr.ts +0 -1
  275. package/src/commands/summary/index.js +0 -1
  276. package/src/commands/tag/index.ts +0 -12
  277. package/src/commands/tag/tag.tsx +0 -215
  278. package/src/commands/tasks/index.ts +0 -11
  279. package/src/commands/tasks/tasks.tsx +0 -8
  280. package/src/commands/teleport/index.js +0 -1
  281. package/src/commands/terminalSetup/index.ts +0 -23
  282. package/src/commands/terminalSetup/terminalSetup.tsx +0 -531
  283. package/src/commands/theme/index.ts +0 -10
  284. package/src/commands/theme/theme.tsx +0 -57
  285. package/src/commands/thinkback/index.ts +0 -13
  286. package/src/commands/thinkback/thinkback.tsx +0 -554
  287. package/src/commands/thinkback-play/index.ts +0 -17
  288. package/src/commands/thinkback-play/thinkback-play.ts +0 -43
  289. package/src/commands/torch.ts +0 -1
  290. package/src/commands/ultraplan.tsx +0 -471
  291. package/src/commands/upgrade/index.ts +0 -16
  292. package/src/commands/upgrade/upgrade.tsx +0 -38
  293. package/src/commands/usage/index.ts +0 -9
  294. package/src/commands/usage/usage.tsx +0 -7
  295. package/src/commands/version.ts +0 -22
  296. package/src/commands/vim/index.ts +0 -11
  297. package/src/commands/vim/vim.ts +0 -38
  298. package/src/commands/voice/index.ts +0 -20
  299. package/src/commands/voice/voice.ts +0 -150
  300. package/src/commands/workflows/index.ts +0 -2
  301. package/src/commands.ts +0 -754
  302. package/src/components/AgentProgressLine.tsx +0 -136
  303. package/src/components/App.tsx +0 -56
  304. package/src/components/ApproveApiKey.tsx +0 -123
  305. package/src/components/AutoModeOptInDialog.tsx +0 -142
  306. package/src/components/AutoUpdater.tsx +0 -198
  307. package/src/components/AutoUpdaterWrapper.tsx +0 -91
  308. package/src/components/AwsAuthStatusBox.tsx +0 -82
  309. package/src/components/BaseTextInput.tsx +0 -136
  310. package/src/components/BashModeProgress.tsx +0 -56
  311. package/src/components/BridgeDialog.tsx +0 -401
  312. package/src/components/BypassPermissionsModeDialog.tsx +0 -87
  313. package/src/components/ChannelDowngradeDialog.tsx +0 -102
  314. package/src/components/ClaudeCodeHint/PluginHintMenu.tsx +0 -78
  315. package/src/components/ClaudeInChromeOnboarding.tsx +0 -121
  316. package/src/components/ClaudeMdExternalIncludesDialog.tsx +0 -137
  317. package/src/components/ClickableImageRef.tsx +0 -73
  318. package/src/components/CompactSummary.tsx +0 -118
  319. package/src/components/ConfigurableShortcutHint.tsx +0 -57
  320. package/src/components/ConsoleOAuthFlow.tsx +0 -631
  321. package/src/components/ContextSuggestions.tsx +0 -47
  322. package/src/components/ContextVisualization.tsx +0 -489
  323. package/src/components/CoordinatorAgentStatus.tsx +0 -273
  324. package/src/components/CostThresholdDialog.tsx +0 -50
  325. package/src/components/CtrlOToExpand.tsx +0 -51
  326. package/src/components/CustomSelect/SelectMulti.tsx +0 -213
  327. package/src/components/CustomSelect/index.ts +0 -3
  328. package/src/components/CustomSelect/option-map.ts +0 -50
  329. package/src/components/CustomSelect/select-input-option.tsx +0 -488
  330. package/src/components/CustomSelect/select-option.tsx +0 -68
  331. package/src/components/CustomSelect/select.tsx +0 -690
  332. package/src/components/CustomSelect/use-multi-select-state.ts +0 -414
  333. package/src/components/CustomSelect/use-select-input.ts +0 -287
  334. package/src/components/CustomSelect/use-select-navigation.ts +0 -653
  335. package/src/components/CustomSelect/use-select-state.ts +0 -157
  336. package/src/components/DesktopHandoff.tsx +0 -193
  337. package/src/components/DesktopUpsell/DesktopUpsellStartup.tsx +0 -171
  338. package/src/components/DevBar.tsx +0 -49
  339. package/src/components/DevChannelsDialog.tsx +0 -105
  340. package/src/components/DiagnosticsDisplay.tsx +0 -95
  341. package/src/components/EffortCallout.tsx +0 -265
  342. package/src/components/EffortIndicator.ts +0 -42
  343. package/src/components/ExitFlow.tsx +0 -48
  344. package/src/components/ExportDialog.tsx +0 -128
  345. package/src/components/FallbackToolUseErrorMessage.tsx +0 -116
  346. package/src/components/FallbackToolUseRejectedMessage.tsx +0 -16
  347. package/src/components/FastIcon.tsx +0 -46
  348. package/src/components/Feedback.tsx +0 -592
  349. package/src/components/FeedbackSurvey/FeedbackSurvey.tsx +0 -174
  350. package/src/components/FeedbackSurvey/FeedbackSurveyView.tsx +0 -108
  351. package/src/components/FeedbackSurvey/TranscriptSharePrompt.tsx +0 -88
  352. package/src/components/FeedbackSurvey/submitTranscriptShare.ts +0 -112
  353. package/src/components/FeedbackSurvey/useDebouncedDigitInput.ts +0 -82
  354. package/src/components/FeedbackSurvey/useFeedbackSurvey.tsx +0 -296
  355. package/src/components/FeedbackSurvey/useFrustrationDetection.ts +0 -2
  356. package/src/components/FeedbackSurvey/useMemorySurvey.tsx +0 -213
  357. package/src/components/FeedbackSurvey/usePostCompactSurvey.tsx +0 -206
  358. package/src/components/FeedbackSurvey/useSurveyState.tsx +0 -100
  359. package/src/components/FeedbackSurvey/utils.ts +0 -2
  360. package/src/components/FileEditToolDiff.tsx +0 -181
  361. package/src/components/FileEditToolUpdatedMessage.tsx +0 -124
  362. package/src/components/FileEditToolUseRejectedMessage.tsx +0 -170
  363. package/src/components/FilePathLink.tsx +0 -43
  364. package/src/components/FullscreenLayout.tsx +0 -637
  365. package/src/components/GlobalSearchDialog.tsx +0 -343
  366. package/src/components/HelpV2/Commands.tsx +0 -82
  367. package/src/components/HelpV2/General.tsx +0 -23
  368. package/src/components/HelpV2/HelpV2.tsx +0 -184
  369. package/src/components/HighlightedCode/Fallback.tsx +0 -193
  370. package/src/components/HighlightedCode.tsx +0 -190
  371. package/src/components/HistorySearchDialog.tsx +0 -118
  372. package/src/components/IdeAutoConnectDialog.tsx +0 -154
  373. package/src/components/IdeOnboardingDialog.tsx +0 -167
  374. package/src/components/IdeStatusIndicator.tsx +0 -58
  375. package/src/components/IdleReturnDialog.tsx +0 -118
  376. package/src/components/InterruptedByUser.tsx +0 -15
  377. package/src/components/InvalidConfigDialog.tsx +0 -156
  378. package/src/components/InvalidSettingsDialog.tsx +0 -89
  379. package/src/components/KeybindingWarnings.tsx +0 -55
  380. package/src/components/LanguagePicker.tsx +0 -86
  381. package/src/components/LogSelector.tsx +0 -1575
  382. package/src/components/LogoV2/AnimatedAsterisk.tsx +0 -50
  383. package/src/components/LogoV2/AnimatedClawd.tsx +0 -124
  384. package/src/components/LogoV2/ChannelsNotice.tsx +0 -266
  385. package/src/components/LogoV2/Clawd.tsx +0 -25
  386. package/src/components/LogoV2/CondensedLogo.tsx +0 -161
  387. package/src/components/LogoV2/EmergencyTip.tsx +0 -58
  388. package/src/components/LogoV2/Feed.tsx +0 -112
  389. package/src/components/LogoV2/FeedColumn.tsx +0 -59
  390. package/src/components/LogoV2/GuestPassesUpsell.tsx +0 -70
  391. package/src/components/LogoV2/LogoV2.tsx +0 -543
  392. package/src/components/LogoV2/Opus1mMergeNotice.tsx +0 -55
  393. package/src/components/LogoV2/OverageCreditUpsell.tsx +0 -166
  394. package/src/components/LogoV2/VoiceModeNotice.tsx +0 -68
  395. package/src/components/LogoV2/WelcomeV2.tsx +0 -433
  396. package/src/components/LogoV2/feedConfigs.tsx +0 -92
  397. package/src/components/LspRecommendation/LspRecommendationMenu.tsx +0 -88
  398. package/src/components/MCPServerApprovalDialog.tsx +0 -115
  399. package/src/components/MCPServerDesktopImportDialog.tsx +0 -203
  400. package/src/components/MCPServerDialogCopy.tsx +0 -15
  401. package/src/components/MCPServerMultiselectDialog.tsx +0 -133
  402. package/src/components/ManagedSettingsSecurityDialog/ManagedSettingsSecurityDialog.tsx +0 -149
  403. package/src/components/ManagedSettingsSecurityDialog/utils.ts +0 -144
  404. package/src/components/Markdown.tsx +0 -236
  405. package/src/components/MarkdownTable.tsx +0 -322
  406. package/src/components/MemoryUsageIndicator.tsx +0 -37
  407. package/src/components/Message.tsx +0 -627
  408. package/src/components/MessageModel.tsx +0 -43
  409. package/src/components/MessageResponse.tsx +0 -78
  410. package/src/components/MessageRow.tsx +0 -383
  411. package/src/components/MessageSelector.tsx +0 -831
  412. package/src/components/MessageTimestamp.tsx +0 -63
  413. package/src/components/Messages.tsx +0 -834
  414. package/src/components/ModelPicker.tsx +0 -448
  415. package/src/components/NativeAutoUpdater.tsx +0 -193
  416. package/src/components/NotebookEditToolUseRejectedMessage.tsx +0 -92
  417. package/src/components/OffscreenFreeze.tsx +0 -44
  418. package/src/components/Onboarding.tsx +0 -244
  419. package/src/components/OutputStylePicker.tsx +0 -112
  420. package/src/components/PackageManagerAutoUpdater.tsx +0 -104
  421. package/src/components/Passes/Passes.tsx +0 -184
  422. package/src/components/PrBadge.tsx +0 -97
  423. package/src/components/PressEnterToContinue.tsx +0 -15
  424. package/src/components/PromptInput/HistorySearchInput.tsx +0 -51
  425. package/src/components/PromptInput/IssueFlagBanner.tsx +0 -12
  426. package/src/components/PromptInput/Notifications.tsx +0 -332
  427. package/src/components/PromptInput/PromptInput.tsx +0 -2339
  428. package/src/components/PromptInput/PromptInputFooter.tsx +0 -191
  429. package/src/components/PromptInput/PromptInputFooterLeftSide.tsx +0 -517
  430. package/src/components/PromptInput/PromptInputFooterSuggestions.tsx +0 -293
  431. package/src/components/PromptInput/PromptInputHelpMenu.tsx +0 -358
  432. package/src/components/PromptInput/PromptInputModeIndicator.tsx +0 -93
  433. package/src/components/PromptInput/PromptInputQueuedCommands.tsx +0 -117
  434. package/src/components/PromptInput/PromptInputStashNotice.tsx +0 -25
  435. package/src/components/PromptInput/SandboxPromptFooterHint.tsx +0 -64
  436. package/src/components/PromptInput/ShimmeredInput.tsx +0 -143
  437. package/src/components/PromptInput/VoiceIndicator.tsx +0 -137
  438. package/src/components/PromptInput/inputModes.ts +0 -33
  439. package/src/components/PromptInput/inputPaste.ts +0 -90
  440. package/src/components/PromptInput/useMaybeTruncateInput.ts +0 -58
  441. package/src/components/PromptInput/usePromptInputPlaceholder.ts +0 -76
  442. package/src/components/PromptInput/useShowFastIconHint.ts +0 -31
  443. package/src/components/PromptInput/useSwarmBanner.ts +0 -155
  444. package/src/components/PromptInput/utils.ts +0 -60
  445. package/src/components/QuickOpenDialog.tsx +0 -244
  446. package/src/components/RemoteCallout.tsx +0 -76
  447. package/src/components/RemoteEnvironmentDialog.tsx +0 -340
  448. package/src/components/ResumeTask.tsx +0 -268
  449. package/src/components/SandboxViolationExpandedView.tsx +0 -99
  450. package/src/components/ScrollKeybindingHandler.tsx +0 -1012
  451. package/src/components/SearchBox.tsx +0 -72
  452. package/src/components/SentryErrorBoundary.ts +0 -28
  453. package/src/components/SessionBackgroundHint.tsx +0 -108
  454. package/src/components/SessionPreview.tsx +0 -194
  455. package/src/components/Settings/Config.tsx +0 -1822
  456. package/src/components/Settings/Settings.tsx +0 -137
  457. package/src/components/Settings/Status.tsx +0 -241
  458. package/src/components/Settings/Usage.tsx +0 -377
  459. package/src/components/ShowInIDEPrompt.tsx +0 -170
  460. package/src/components/SkillImprovementSurvey.tsx +0 -152
  461. package/src/components/Spinner/FlashingChar.tsx +0 -61
  462. package/src/components/Spinner/GlimmerMessage.tsx +0 -328
  463. package/src/components/Spinner/ShimmerChar.tsx +0 -36
  464. package/src/components/Spinner/SpinnerAnimationRow.tsx +0 -265
  465. package/src/components/Spinner/SpinnerGlyph.tsx +0 -80
  466. package/src/components/Spinner/TeammateSpinnerLine.tsx +0 -233
  467. package/src/components/Spinner/TeammateSpinnerTree.tsx +0 -272
  468. package/src/components/Spinner/index.ts +0 -10
  469. package/src/components/Spinner/teammateSelectHint.ts +0 -1
  470. package/src/components/Spinner/types.ts +0 -2
  471. package/src/components/Spinner/useShimmerAnimation.ts +0 -31
  472. package/src/components/Spinner/useStalledAnimation.ts +0 -75
  473. package/src/components/Spinner/utils.ts +0 -84
  474. package/src/components/Spinner.tsx +0 -562
  475. package/src/components/Stats.tsx +0 -1228
  476. package/src/components/StatusLine.tsx +0 -324
  477. package/src/components/StatusNotices.tsx +0 -55
  478. package/src/components/StructuredDiff/Fallback.tsx +0 -487
  479. package/src/components/StructuredDiff/colorDiff.ts +0 -37
  480. package/src/components/StructuredDiff.tsx +0 -190
  481. package/src/components/StructuredDiffList.tsx +0 -30
  482. package/src/components/TagTabs.tsx +0 -139
  483. package/src/components/TaskListV2.tsx +0 -378
  484. package/src/components/TeammateViewHeader.tsx +0 -82
  485. package/src/components/TeleportError.tsx +0 -189
  486. package/src/components/TeleportProgress.tsx +0 -140
  487. package/src/components/TeleportRepoMismatchDialog.tsx +0 -104
  488. package/src/components/TeleportResumeWrapper.tsx +0 -167
  489. package/src/components/TeleportStash.tsx +0 -116
  490. package/src/components/TextInput.tsx +0 -124
  491. package/src/components/ThemePicker.tsx +0 -333
  492. package/src/components/ThinkingToggle.tsx +0 -153
  493. package/src/components/TokenWarning.tsx +0 -179
  494. package/src/components/ToolUseLoader.tsx +0 -42
  495. package/src/components/TrustDialog/TrustDialog.tsx +0 -290
  496. package/src/components/TrustDialog/utils.ts +0 -245
  497. package/src/components/ValidationErrorsList.tsx +0 -148
  498. package/src/components/VimTextInput.tsx +0 -140
  499. package/src/components/VirtualMessageList.tsx +0 -1082
  500. package/src/components/WorkflowMultiselectDialog.tsx +0 -128
  501. package/src/components/WorktreeExitDialog.tsx +0 -231
  502. package/src/components/agents/AgentDetail.tsx +0 -220
  503. package/src/components/agents/AgentEditor.tsx +0 -178
  504. package/src/components/agents/AgentNavigationFooter.tsx +0 -26
  505. package/src/components/agents/AgentsList.tsx +0 -440
  506. package/src/components/agents/AgentsMenu.tsx +0 -800
  507. package/src/components/agents/ColorPicker.tsx +0 -112
  508. package/src/components/agents/ModelSelector.tsx +0 -68
  509. package/src/components/agents/SnapshotUpdateDialog.ts +0 -2
  510. package/src/components/agents/ToolSelector.tsx +0 -562
  511. package/src/components/agents/agentFileUtils.ts +0 -272
  512. package/src/components/agents/generateAgent.ts +0 -197
  513. package/src/components/agents/new-agent-creation/CreateAgentWizard.tsx +0 -97
  514. package/src/components/agents/new-agent-creation/types.ts +0 -1
  515. package/src/components/agents/new-agent-creation/wizard-steps/ColorStep.tsx +0 -84
  516. package/src/components/agents/new-agent-creation/wizard-steps/ConfirmStep.tsx +0 -378
  517. package/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsx +0 -74
  518. package/src/components/agents/new-agent-creation/wizard-steps/DescriptionStep.tsx +0 -123
  519. package/src/components/agents/new-agent-creation/wizard-steps/GenerateStep.tsx +0 -143
  520. package/src/components/agents/new-agent-creation/wizard-steps/LocationStep.tsx +0 -80
  521. package/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsx +0 -113
  522. package/src/components/agents/new-agent-creation/wizard-steps/MethodStep.tsx +0 -80
  523. package/src/components/agents/new-agent-creation/wizard-steps/ModelStep.tsx +0 -52
  524. package/src/components/agents/new-agent-creation/wizard-steps/PromptStep.tsx +0 -128
  525. package/src/components/agents/new-agent-creation/wizard-steps/ToolsStep.tsx +0 -61
  526. package/src/components/agents/new-agent-creation/wizard-steps/TypeStep.tsx +0 -103
  527. package/src/components/agents/types.ts +0 -27
  528. package/src/components/agents/utils.ts +0 -18
  529. package/src/components/agents/validateAgent.ts +0 -109
  530. package/src/components/design-system/Byline.tsx +0 -77
  531. package/src/components/design-system/Dialog.tsx +0 -138
  532. package/src/components/design-system/Divider.tsx +0 -149
  533. package/src/components/design-system/FuzzyPicker.tsx +0 -312
  534. package/src/components/design-system/KeyboardShortcutHint.tsx +0 -81
  535. package/src/components/design-system/ListItem.tsx +0 -244
  536. package/src/components/design-system/LoadingState.tsx +0 -94
  537. package/src/components/design-system/Pane.tsx +0 -77
  538. package/src/components/design-system/ProgressBar.tsx +0 -86
  539. package/src/components/design-system/Ratchet.tsx +0 -80
  540. package/src/components/design-system/StatusIcon.tsx +0 -95
  541. package/src/components/design-system/Tabs.tsx +0 -340
  542. package/src/components/design-system/ThemeProvider.tsx +0 -170
  543. package/src/components/design-system/ThemedBox.tsx +0 -156
  544. package/src/components/design-system/ThemedText.tsx +0 -124
  545. package/src/components/design-system/color.ts +0 -30
  546. package/src/components/diff/DiffDetailView.tsx +0 -281
  547. package/src/components/diff/DiffDialog.tsx +0 -383
  548. package/src/components/diff/DiffFileList.tsx +0 -292
  549. package/src/components/grove/Grove.tsx +0 -463
  550. package/src/components/hooks/HooksConfigMenu.tsx +0 -578
  551. package/src/components/hooks/PromptDialog.tsx +0 -90
  552. package/src/components/hooks/SelectEventMode.tsx +0 -127
  553. package/src/components/hooks/SelectHookMode.tsx +0 -112
  554. package/src/components/hooks/SelectMatcherMode.tsx +0 -144
  555. package/src/components/hooks/ViewHookMode.tsx +0 -199
  556. package/src/components/mcp/CapabilitiesSection.tsx +0 -61
  557. package/src/components/mcp/ElicitationDialog.tsx +0 -1169
  558. package/src/components/mcp/MCPAgentServerMenu.tsx +0 -183
  559. package/src/components/mcp/MCPListPanel.tsx +0 -504
  560. package/src/components/mcp/MCPReconnect.tsx +0 -167
  561. package/src/components/mcp/MCPRemoteServerMenu.tsx +0 -649
  562. package/src/components/mcp/MCPSettings.tsx +0 -398
  563. package/src/components/mcp/MCPStdioServerMenu.tsx +0 -177
  564. package/src/components/mcp/MCPToolDetailView.tsx +0 -212
  565. package/src/components/mcp/MCPToolListView.tsx +0 -141
  566. package/src/components/mcp/McpParsingWarnings.tsx +0 -213
  567. package/src/components/mcp/index.ts +0 -9
  568. package/src/components/mcp/types.ts +0 -7
  569. package/src/components/mcp/utils/reconnectHelpers.tsx +0 -49
  570. package/src/components/memory/MemoryFileSelector.tsx +0 -438
  571. package/src/components/memory/MemoryUpdateNotification.tsx +0 -45
  572. package/src/components/messageActions.tsx +0 -450
  573. package/src/components/messages/AdvisorMessage.tsx +0 -158
  574. package/src/components/messages/AssistantRedactedThinkingMessage.tsx +0 -31
  575. package/src/components/messages/AssistantTextMessage.tsx +0 -270
  576. package/src/components/messages/AssistantThinkingMessage.tsx +0 -86
  577. package/src/components/messages/AssistantToolUseMessage.tsx +0 -368
  578. package/src/components/messages/AttachmentMessage.tsx +0 -536
  579. package/src/components/messages/CollapsedReadSearchContent.tsx +0 -484
  580. package/src/components/messages/CompactBoundaryMessage.tsx +0 -18
  581. package/src/components/messages/GroupedToolUseContent.tsx +0 -58
  582. package/src/components/messages/HighlightedThinkingText.tsx +0 -162
  583. package/src/components/messages/HookProgressMessage.tsx +0 -116
  584. package/src/components/messages/PlanApprovalMessage.tsx +0 -222
  585. package/src/components/messages/RateLimitMessage.tsx +0 -161
  586. package/src/components/messages/ShutdownMessage.tsx +0 -132
  587. package/src/components/messages/SnipBoundaryMessage.ts +0 -2
  588. package/src/components/messages/SystemAPIErrorMessage.tsx +0 -141
  589. package/src/components/messages/SystemTextMessage.tsx +0 -827
  590. package/src/components/messages/TaskAssignmentMessage.tsx +0 -76
  591. package/src/components/messages/UserAgentNotificationMessage.tsx +0 -83
  592. package/src/components/messages/UserBashInputMessage.tsx +0 -58
  593. package/src/components/messages/UserBashOutputMessage.tsx +0 -54
  594. package/src/components/messages/UserChannelMessage.tsx +0 -137
  595. package/src/components/messages/UserCommandMessage.tsx +0 -108
  596. package/src/components/messages/UserCrossSessionMessage.ts +0 -2
  597. package/src/components/messages/UserForkBoilerplateMessage.ts +0 -2
  598. package/src/components/messages/UserGitHubWebhookMessage.ts +0 -2
  599. package/src/components/messages/UserImageMessage.tsx +0 -59
  600. package/src/components/messages/UserLocalCommandOutputMessage.tsx +0 -167
  601. package/src/components/messages/UserMemoryInputMessage.tsx +0 -75
  602. package/src/components/messages/UserPlanMessage.tsx +0 -42
  603. package/src/components/messages/UserPromptMessage.tsx +0 -80
  604. package/src/components/messages/UserResourceUpdateMessage.tsx +0 -121
  605. package/src/components/messages/UserTeammateMessage.tsx +0 -206
  606. package/src/components/messages/UserTextMessage.tsx +0 -275
  607. package/src/components/messages/UserToolResultMessage/RejectedPlanMessage.tsx +0 -31
  608. package/src/components/messages/UserToolResultMessage/RejectedToolUseMessage.tsx +0 -16
  609. package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +0 -16
  610. package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +0 -103
  611. package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +0 -95
  612. package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +0 -106
  613. package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +0 -104
  614. package/src/components/messages/UserToolResultMessage/utils.tsx +0 -44
  615. package/src/components/messages/nullRenderingAttachments.ts +0 -70
  616. package/src/components/messages/teamMemCollapsed.tsx +0 -140
  617. package/src/components/messages/teamMemSaved.ts +0 -19
  618. package/src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.tsx +0 -645
  619. package/src/components/permissions/AskUserQuestionPermissionRequest/PreviewBox.tsx +0 -229
  620. package/src/components/permissions/AskUserQuestionPermissionRequest/PreviewQuestionView.tsx +0 -328
  621. package/src/components/permissions/AskUserQuestionPermissionRequest/QuestionNavigationBar.tsx +0 -178
  622. package/src/components/permissions/AskUserQuestionPermissionRequest/QuestionView.tsx +0 -465
  623. package/src/components/permissions/AskUserQuestionPermissionRequest/SubmitQuestionsView.tsx +0 -144
  624. package/src/components/permissions/AskUserQuestionPermissionRequest/use-multiple-choice-state.ts +0 -179
  625. package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +0 -482
  626. package/src/components/permissions/BashPermissionRequest/bashToolUseOptions.tsx +0 -147
  627. package/src/components/permissions/ComputerUseApproval/ComputerUseApproval.tsx +0 -441
  628. package/src/components/permissions/EnterPlanModePermissionRequest/EnterPlanModePermissionRequest.tsx +0 -122
  629. package/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx +0 -768
  630. package/src/components/permissions/FallbackPermissionRequest.tsx +0 -333
  631. package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +0 -182
  632. package/src/components/permissions/FilePermissionDialog/FilePermissionDialog.tsx +0 -204
  633. package/src/components/permissions/FilePermissionDialog/ideDiffConfig.ts +0 -42
  634. package/src/components/permissions/FilePermissionDialog/permissionOptions.tsx +0 -177
  635. package/src/components/permissions/FilePermissionDialog/useFilePermissionDialog.ts +0 -212
  636. package/src/components/permissions/FilePermissionDialog/usePermissionHandler.ts +0 -185
  637. package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +0 -161
  638. package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +0 -89
  639. package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +0 -115
  640. package/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +0 -2
  641. package/src/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.tsx +0 -166
  642. package/src/components/permissions/NotebookEditPermissionRequest/NotebookEditToolDiff.tsx +0 -235
  643. package/src/components/permissions/PermissionDecisionDebugInfo.tsx +0 -460
  644. package/src/components/permissions/PermissionDialog.tsx +0 -72
  645. package/src/components/permissions/PermissionExplanation.tsx +0 -272
  646. package/src/components/permissions/PermissionPrompt.tsx +0 -336
  647. package/src/components/permissions/PermissionRequest.tsx +0 -217
  648. package/src/components/permissions/PermissionRequestTitle.tsx +0 -66
  649. package/src/components/permissions/PermissionRuleExplanation.tsx +0 -121
  650. package/src/components/permissions/PowerShellPermissionRequest/PowerShellPermissionRequest.tsx +0 -235
  651. package/src/components/permissions/PowerShellPermissionRequest/powershellToolUseOptions.tsx +0 -91
  652. package/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +0 -2
  653. package/src/components/permissions/SandboxPermissionRequest.tsx +0 -163
  654. package/src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.tsx +0 -230
  655. package/src/components/permissions/SkillPermissionRequest/SkillPermissionRequest.tsx +0 -369
  656. package/src/components/permissions/WebFetchPermissionRequest/WebFetchPermissionRequest.tsx +0 -258
  657. package/src/components/permissions/WorkerBadge.tsx +0 -49
  658. package/src/components/permissions/WorkerPendingPermission.tsx +0 -105
  659. package/src/components/permissions/hooks.ts +0 -209
  660. package/src/components/permissions/rules/AddPermissionRules.tsx +0 -180
  661. package/src/components/permissions/rules/AddWorkspaceDirectory.tsx +0 -340
  662. package/src/components/permissions/rules/PermissionRuleDescription.tsx +0 -76
  663. package/src/components/permissions/rules/PermissionRuleInput.tsx +0 -138
  664. package/src/components/permissions/rules/PermissionRuleList.tsx +0 -1179
  665. package/src/components/permissions/rules/RecentDenialsTab.tsx +0 -207
  666. package/src/components/permissions/rules/RemoveWorkspaceDirectory.tsx +0 -110
  667. package/src/components/permissions/rules/WorkspaceTab.tsx +0 -150
  668. package/src/components/permissions/shellPermissionHelpers.tsx +0 -164
  669. package/src/components/permissions/useShellPermissionFeedback.ts +0 -148
  670. package/src/components/permissions/utils.ts +0 -25
  671. package/src/components/sandbox/SandboxConfigTab.tsx +0 -45
  672. package/src/components/sandbox/SandboxDependenciesTab.tsx +0 -120
  673. package/src/components/sandbox/SandboxDoctorSection.tsx +0 -46
  674. package/src/components/sandbox/SandboxOverridesTab.tsx +0 -193
  675. package/src/components/sandbox/SandboxSettings.tsx +0 -296
  676. package/src/components/shell/ExpandShellOutputContext.tsx +0 -36
  677. package/src/components/shell/OutputLine.tsx +0 -118
  678. package/src/components/shell/ShellProgressMessage.tsx +0 -150
  679. package/src/components/shell/ShellTimeDisplay.tsx +0 -74
  680. package/src/components/skills/SkillsMenu.tsx +0 -237
  681. package/src/components/tasks/AsyncAgentDetailDialog.tsx +0 -229
  682. package/src/components/tasks/BackgroundTask.tsx +0 -345
  683. package/src/components/tasks/BackgroundTaskStatus.tsx +0 -429
  684. package/src/components/tasks/BackgroundTasksDialog.tsx +0 -652
  685. package/src/components/tasks/DreamDetailDialog.tsx +0 -251
  686. package/src/components/tasks/InProcessTeammateDetailDialog.tsx +0 -266
  687. package/src/components/tasks/MonitorMcpDetailDialog.ts +0 -2
  688. package/src/components/tasks/RemoteSessionDetailDialog.tsx +0 -904
  689. package/src/components/tasks/RemoteSessionProgress.tsx +0 -243
  690. package/src/components/tasks/ShellDetailDialog.tsx +0 -404
  691. package/src/components/tasks/ShellProgress.tsx +0 -87
  692. package/src/components/tasks/WorkflowDetailDialog.ts +0 -2
  693. package/src/components/tasks/renderToolActivity.tsx +0 -33
  694. package/src/components/tasks/taskStatusUtils.tsx +0 -107
  695. package/src/components/teams/TeamStatus.tsx +0 -80
  696. package/src/components/teams/TeamsDialog.tsx +0 -715
  697. package/src/components/ui/OrderedList.tsx +0 -71
  698. package/src/components/ui/OrderedListItem.tsx +0 -45
  699. package/src/components/ui/TreeSelect.tsx +0 -397
  700. package/src/components/ui/option.ts +0 -4
  701. package/src/components/wizard/WizardDialogLayout.tsx +0 -65
  702. package/src/components/wizard/WizardNavigationFooter.tsx +0 -24
  703. package/src/components/wizard/WizardProvider.tsx +0 -213
  704. package/src/components/wizard/index.ts +0 -9
  705. package/src/components/wizard/types.ts +0 -3
  706. package/src/components/wizard/useWizard.ts +0 -13
  707. package/src/constants/apiLimits.ts +0 -94
  708. package/src/constants/betas.ts +0 -52
  709. package/src/constants/common.ts +0 -33
  710. package/src/constants/cyberRiskInstruction.ts +0 -24
  711. package/src/constants/errorIds.ts +0 -15
  712. package/src/constants/figures.ts +0 -45
  713. package/src/constants/files.ts +0 -156
  714. package/src/constants/github-app.ts +0 -144
  715. package/src/constants/keys.ts +0 -11
  716. package/src/constants/messages.ts +0 -1
  717. package/src/constants/oauth.ts +0 -234
  718. package/src/constants/outputStyles.ts +0 -216
  719. package/src/constants/product.ts +0 -76
  720. package/src/constants/prompts.ts +0 -915
  721. package/src/constants/querySource.ts +0 -1
  722. package/src/constants/spinnerVerbs.ts +0 -204
  723. package/src/constants/system.ts +0 -95
  724. package/src/constants/systemPromptSections.ts +0 -68
  725. package/src/constants/toolLimits.ts +0 -56
  726. package/src/constants/tools.ts +0 -112
  727. package/src/constants/turnCompletionVerbs.ts +0 -12
  728. package/src/constants/xml.ts +0 -86
  729. package/src/context/QueuedMessageContext.tsx +0 -63
  730. package/src/context/fpsMetrics.tsx +0 -30
  731. package/src/context/mailbox.tsx +0 -38
  732. package/src/context/modalContext.tsx +0 -58
  733. package/src/context/notifications.tsx +0 -240
  734. package/src/context/overlayContext.tsx +0 -151
  735. package/src/context/promptOverlayContext.tsx +0 -125
  736. package/src/context/stats.tsx +0 -220
  737. package/src/context/voice.tsx +0 -88
  738. package/src/context.ts +0 -189
  739. package/src/coordinator/coordinatorMode.ts +0 -369
  740. package/src/coordinator/workerAgent.ts +0 -2
  741. package/src/cost-tracker.ts +0 -323
  742. package/src/costHook.ts +0 -22
  743. package/src/daemon/main.ts +0 -2
  744. package/src/daemon/workerRegistry.ts +0 -2
  745. package/src/dialogLaunchers.tsx +0 -133
  746. package/src/engine/CostMapper.ts +0 -57
  747. package/src/engine/MessageMapper.ts +0 -276
  748. package/src/engine/ModelResolver.ts +0 -153
  749. package/src/engine/PermissionBridge.ts +0 -114
  750. package/src/engine/PiAgentAdapter.ts +0 -299
  751. package/src/engine/SubagentTools.ts +0 -92
  752. package/src/engine/ToolAdapter.ts +0 -122
  753. package/src/engine/engine-backup/CostMapper.ts +0 -57
  754. package/src/engine/engine-backup/MessageMapper.ts +0 -276
  755. package/src/engine/engine-backup/ModelResolver.ts +0 -153
  756. package/src/engine/engine-backup/PermissionBridge.ts +0 -114
  757. package/src/engine/engine-backup/PiAgentAdapter.ts +0 -299
  758. package/src/engine/engine-backup/SubagentTools.ts +0 -92
  759. package/src/engine/engine-backup/ToolAdapter.ts +0 -122
  760. package/src/engine/engine-backup/index.ts +0 -14
  761. package/src/engine/engine-backup/piQueryBridge.ts +0 -396
  762. package/src/engine/index.ts +0 -14
  763. package/src/engine/piQueryBridge.ts +0 -396
  764. package/src/entrypoints/agentSdkTypes.ts +0 -443
  765. package/src/entrypoints/cli.tsx +0 -303
  766. package/src/entrypoints/init.ts +0 -340
  767. package/src/entrypoints/mcp.ts +0 -196
  768. package/src/entrypoints/sandboxTypes.ts +0 -156
  769. package/src/entrypoints/sdk/controlSchemas.ts +0 -663
  770. package/src/entrypoints/sdk/controlTypes.ts +0 -12
  771. package/src/entrypoints/sdk/coreSchemas.ts +0 -1889
  772. package/src/entrypoints/sdk/coreTypes.generated.ts +0 -1
  773. package/src/entrypoints/sdk/coreTypes.ts +0 -62
  774. package/src/entrypoints/sdk/runtimeTypes.ts +0 -18
  775. package/src/entrypoints/sdk/sdkUtilityTypes.ts +0 -1
  776. package/src/entrypoints/sdk/settingsTypes.generated.ts +0 -1
  777. package/src/entrypoints/sdk/toolTypes.ts +0 -2
  778. package/src/environment-runner/main.ts +0 -2
  779. package/src/history.ts +0 -464
  780. package/src/hooks/fileSuggestions.ts +0 -811
  781. package/src/hooks/notifs/useAntOrgWarningNotification.ts +0 -2
  782. package/src/hooks/notifs/useAutoModeUnavailableNotification.ts +0 -56
  783. package/src/hooks/notifs/useCanSwitchToExistingSubscription.tsx +0 -60
  784. package/src/hooks/notifs/useDeprecationWarningNotification.tsx +0 -44
  785. package/src/hooks/notifs/useFastModeNotification.tsx +0 -162
  786. package/src/hooks/notifs/useIDEStatusIndicator.tsx +0 -186
  787. package/src/hooks/notifs/useInstallMessages.tsx +0 -26
  788. package/src/hooks/notifs/useLspInitializationNotification.tsx +0 -143
  789. package/src/hooks/notifs/useMcpConnectivityStatus.tsx +0 -88
  790. package/src/hooks/notifs/useModelMigrationNotifications.tsx +0 -52
  791. package/src/hooks/notifs/useNpmDeprecationNotification.tsx +0 -25
  792. package/src/hooks/notifs/usePluginAutoupdateNotification.tsx +0 -83
  793. package/src/hooks/notifs/usePluginInstallationStatus.tsx +0 -128
  794. package/src/hooks/notifs/useRateLimitWarningNotification.tsx +0 -114
  795. package/src/hooks/notifs/useSettingsErrors.tsx +0 -69
  796. package/src/hooks/notifs/useStartupNotification.ts +0 -41
  797. package/src/hooks/notifs/useTeammateShutdownNotification.ts +0 -78
  798. package/src/hooks/renderPlaceholder.ts +0 -51
  799. package/src/hooks/toolPermission/PermissionContext.ts +0 -388
  800. package/src/hooks/toolPermission/handlers/coordinatorHandler.ts +0 -65
  801. package/src/hooks/toolPermission/handlers/interactiveHandler.ts +0 -536
  802. package/src/hooks/toolPermission/handlers/swarmWorkerHandler.ts +0 -159
  803. package/src/hooks/toolPermission/permissionLogging.ts +0 -238
  804. package/src/hooks/unifiedSuggestions.ts +0 -202
  805. package/src/hooks/useAfterFirstRender.ts +0 -17
  806. package/src/hooks/useApiKeyVerification.ts +0 -84
  807. package/src/hooks/useArrowKeyHistory.tsx +0 -229
  808. package/src/hooks/useAssistantHistory.ts +0 -250
  809. package/src/hooks/useAwaySummary.ts +0 -125
  810. package/src/hooks/useBackgroundTaskNavigation.ts +0 -251
  811. package/src/hooks/useBlink.ts +0 -34
  812. package/src/hooks/useCanUseTool.tsx +0 -204
  813. package/src/hooks/useCancelRequest.ts +0 -276
  814. package/src/hooks/useChromeExtensionNotification.tsx +0 -50
  815. package/src/hooks/useClaudeCodeHintRecommendation.tsx +0 -129
  816. package/src/hooks/useClipboardImageHint.ts +0 -77
  817. package/src/hooks/useCommandKeybindings.tsx +0 -108
  818. package/src/hooks/useCommandQueue.ts +0 -15
  819. package/src/hooks/useCopyOnSelect.ts +0 -98
  820. package/src/hooks/useDeferredHookMessages.ts +0 -46
  821. package/src/hooks/useDiffData.ts +0 -110
  822. package/src/hooks/useDiffInIDE.ts +0 -379
  823. package/src/hooks/useDirectConnect.ts +0 -229
  824. package/src/hooks/useDoublePress.ts +0 -62
  825. package/src/hooks/useDynamicConfig.ts +0 -22
  826. package/src/hooks/useElapsedTime.ts +0 -37
  827. package/src/hooks/useExitOnCtrlCD.ts +0 -95
  828. package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +0 -24
  829. package/src/hooks/useFileHistorySnapshotInit.ts +0 -25
  830. package/src/hooks/useGlobalKeybindings.tsx +0 -249
  831. package/src/hooks/useHistorySearch.ts +0 -303
  832. package/src/hooks/useIDEIntegration.tsx +0 -70
  833. package/src/hooks/useIdeAtMentioned.ts +0 -76
  834. package/src/hooks/useIdeConnectionStatus.ts +0 -33
  835. package/src/hooks/useIdeLogging.ts +0 -41
  836. package/src/hooks/useIdeSelection.ts +0 -150
  837. package/src/hooks/useInboxPoller.ts +0 -969
  838. package/src/hooks/useInputBuffer.ts +0 -132
  839. package/src/hooks/useIssueFlagBanner.ts +0 -133
  840. package/src/hooks/useLogMessages.ts +0 -119
  841. package/src/hooks/useLspPluginRecommendation.tsx +0 -194
  842. package/src/hooks/useMailboxBridge.ts +0 -21
  843. package/src/hooks/useMainLoopModel.ts +0 -34
  844. package/src/hooks/useManagePlugins.ts +0 -304
  845. package/src/hooks/useMemoryUsage.ts +0 -39
  846. package/src/hooks/useMergedClients.ts +0 -23
  847. package/src/hooks/useMergedCommands.ts +0 -15
  848. package/src/hooks/useMergedTools.ts +0 -44
  849. package/src/hooks/useMinDisplayTime.ts +0 -35
  850. package/src/hooks/useNotifyAfterTimeout.ts +0 -65
  851. package/src/hooks/useOfficialMarketplaceNotification.tsx +0 -48
  852. package/src/hooks/usePasteHandler.ts +0 -285
  853. package/src/hooks/usePluginRecommendationBase.tsx +0 -105
  854. package/src/hooks/usePrStatus.ts +0 -106
  855. package/src/hooks/usePromptSuggestion.ts +0 -177
  856. package/src/hooks/usePromptsFromClaudeInChrome.tsx +0 -71
  857. package/src/hooks/useQueueProcessor.ts +0 -68
  858. package/src/hooks/useRemoteSession.ts +0 -605
  859. package/src/hooks/useReplBridge.tsx +0 -723
  860. package/src/hooks/useSSHSession.ts +0 -241
  861. package/src/hooks/useScheduledTasks.ts +0 -139
  862. package/src/hooks/useSearchInput.ts +0 -364
  863. package/src/hooks/useSessionBackgrounding.ts +0 -158
  864. package/src/hooks/useSettings.ts +0 -17
  865. package/src/hooks/useSettingsChange.ts +0 -25
  866. package/src/hooks/useSkillImprovementSurvey.ts +0 -105
  867. package/src/hooks/useSkillsChange.ts +0 -62
  868. package/src/hooks/useSwarmInitialization.ts +0 -81
  869. package/src/hooks/useSwarmPermissionPoller.ts +0 -330
  870. package/src/hooks/useTaskListWatcher.ts +0 -221
  871. package/src/hooks/useTasksV2.ts +0 -250
  872. package/src/hooks/useTeammateViewAutoExit.ts +0 -63
  873. package/src/hooks/useTeleportResume.tsx +0 -85
  874. package/src/hooks/useTerminalSize.ts +0 -15
  875. package/src/hooks/useTextInput.ts +0 -529
  876. package/src/hooks/useTimeout.ts +0 -14
  877. package/src/hooks/useTurnDiffs.ts +0 -213
  878. package/src/hooks/useTypeahead.tsx +0 -1385
  879. package/src/hooks/useUpdateNotification.ts +0 -34
  880. package/src/hooks/useVimInput.ts +0 -316
  881. package/src/hooks/useVirtualScroll.ts +0 -721
  882. package/src/hooks/useVoice.ts +0 -1144
  883. package/src/hooks/useVoiceEnabled.ts +0 -25
  884. package/src/hooks/useVoiceIntegration.tsx +0 -677
  885. package/src/hunter.ts +0 -1
  886. package/src/ink/Ansi.tsx +0 -292
  887. package/src/ink/bidi.ts +0 -139
  888. package/src/ink/clearTerminal.ts +0 -74
  889. package/src/ink/colorize.ts +0 -231
  890. package/src/ink/components/AlternateScreen.tsx +0 -80
  891. package/src/ink/components/App.tsx +0 -658
  892. package/src/ink/components/AppContext.ts +0 -21
  893. package/src/ink/components/Box.tsx +0 -214
  894. package/src/ink/components/Button.tsx +0 -192
  895. package/src/ink/components/ClockContext.tsx +0 -112
  896. package/src/ink/components/CursorDeclarationContext.ts +0 -32
  897. package/src/ink/components/ErrorOverview.tsx +0 -109
  898. package/src/ink/components/Link.tsx +0 -42
  899. package/src/ink/components/Newline.tsx +0 -39
  900. package/src/ink/components/NoSelect.tsx +0 -68
  901. package/src/ink/components/RawAnsi.tsx +0 -57
  902. package/src/ink/components/ScrollBox.tsx +0 -237
  903. package/src/ink/components/Spacer.tsx +0 -20
  904. package/src/ink/components/StdinContext.ts +0 -49
  905. package/src/ink/components/TerminalFocusContext.tsx +0 -52
  906. package/src/ink/components/TerminalSizeContext.tsx +0 -7
  907. package/src/ink/components/Text.tsx +0 -254
  908. package/src/ink/constants.ts +0 -2
  909. package/src/ink/cursor.ts +0 -1
  910. package/src/ink/devtools.ts +0 -2
  911. package/src/ink/dom.ts +0 -484
  912. package/src/ink/events/click-event.ts +0 -38
  913. package/src/ink/events/dispatcher.ts +0 -233
  914. package/src/ink/events/emitter.ts +0 -39
  915. package/src/ink/events/event-handlers.ts +0 -73
  916. package/src/ink/events/event.ts +0 -11
  917. package/src/ink/events/focus-event.ts +0 -21
  918. package/src/ink/events/input-event.ts +0 -205
  919. package/src/ink/events/keyboard-event.ts +0 -51
  920. package/src/ink/events/paste-event.ts +0 -1
  921. package/src/ink/events/resize-event.ts +0 -1
  922. package/src/ink/events/terminal-event.ts +0 -107
  923. package/src/ink/events/terminal-focus-event.ts +0 -19
  924. package/src/ink/focus.ts +0 -181
  925. package/src/ink/frame.ts +0 -124
  926. package/src/ink/get-max-width.ts +0 -27
  927. package/src/ink/global.d.ts +0 -1
  928. package/src/ink/hit-test.ts +0 -130
  929. package/src/ink/hooks/use-animation-frame.ts +0 -57
  930. package/src/ink/hooks/use-app.ts +0 -8
  931. package/src/ink/hooks/use-declared-cursor.ts +0 -73
  932. package/src/ink/hooks/use-input.ts +0 -92
  933. package/src/ink/hooks/use-interval.ts +0 -67
  934. package/src/ink/hooks/use-search-highlight.ts +0 -53
  935. package/src/ink/hooks/use-selection.ts +0 -104
  936. package/src/ink/hooks/use-stdin.ts +0 -8
  937. package/src/ink/hooks/use-tab-status.ts +0 -72
  938. package/src/ink/hooks/use-terminal-focus.ts +0 -16
  939. package/src/ink/hooks/use-terminal-title.ts +0 -31
  940. package/src/ink/hooks/use-terminal-viewport.ts +0 -96
  941. package/src/ink/ink.tsx +0 -1723
  942. package/src/ink/instances.ts +0 -10
  943. package/src/ink/layout/engine.ts +0 -6
  944. package/src/ink/layout/geometry.ts +0 -97
  945. package/src/ink/layout/node.ts +0 -152
  946. package/src/ink/layout/yoga.ts +0 -308
  947. package/src/ink/line-width-cache.ts +0 -24
  948. package/src/ink/log-update.ts +0 -773
  949. package/src/ink/measure-element.ts +0 -23
  950. package/src/ink/measure-text.ts +0 -47
  951. package/src/ink/node-cache.ts +0 -54
  952. package/src/ink/optimizer.ts +0 -93
  953. package/src/ink/output.ts +0 -797
  954. package/src/ink/parse-keypress.ts +0 -801
  955. package/src/ink/reconciler.ts +0 -512
  956. package/src/ink/render-border.ts +0 -231
  957. package/src/ink/render-node-to-output.ts +0 -1462
  958. package/src/ink/render-to-screen.ts +0 -231
  959. package/src/ink/renderer.ts +0 -178
  960. package/src/ink/root.ts +0 -184
  961. package/src/ink/screen.ts +0 -1486
  962. package/src/ink/searchHighlight.ts +0 -93
  963. package/src/ink/selection.ts +0 -917
  964. package/src/ink/squash-text-nodes.ts +0 -92
  965. package/src/ink/stringWidth.ts +0 -222
  966. package/src/ink/styles.ts +0 -771
  967. package/src/ink/supports-hyperlinks.ts +0 -57
  968. package/src/ink/tabstops.ts +0 -46
  969. package/src/ink/terminal-focus-state.ts +0 -47
  970. package/src/ink/terminal-querier.ts +0 -212
  971. package/src/ink/terminal.ts +0 -248
  972. package/src/ink/termio/ansi.ts +0 -75
  973. package/src/ink/termio/csi.ts +0 -319
  974. package/src/ink/termio/dec.ts +0 -60
  975. package/src/ink/termio/esc.ts +0 -67
  976. package/src/ink/termio/osc.ts +0 -493
  977. package/src/ink/termio/parser.ts +0 -394
  978. package/src/ink/termio/sgr.ts +0 -308
  979. package/src/ink/termio/tokenize.ts +0 -319
  980. package/src/ink/termio/types.ts +0 -236
  981. package/src/ink/termio.ts +0 -42
  982. package/src/ink/useTerminalNotification.ts +0 -126
  983. package/src/ink/warn.ts +0 -9
  984. package/src/ink/widest-line.ts +0 -19
  985. package/src/ink/wrap-text.ts +0 -74
  986. package/src/ink/wrapAnsi.ts +0 -20
  987. package/src/ink.ts +0 -85
  988. package/src/interactiveHelpers.tsx +0 -366
  989. package/src/jobs/classifier.ts +0 -2
  990. package/src/keybindings/KeybindingContext.tsx +0 -243
  991. package/src/keybindings/KeybindingProviderSetup.tsx +0 -308
  992. package/src/keybindings/defaultBindings.ts +0 -340
  993. package/src/keybindings/loadUserBindings.ts +0 -472
  994. package/src/keybindings/match.ts +0 -120
  995. package/src/keybindings/parser.ts +0 -203
  996. package/src/keybindings/reservedShortcuts.ts +0 -127
  997. package/src/keybindings/resolver.ts +0 -244
  998. package/src/keybindings/schema.ts +0 -236
  999. package/src/keybindings/shortcutFormat.ts +0 -63
  1000. package/src/keybindings/template.ts +0 -52
  1001. package/src/keybindings/types.ts +0 -3
  1002. package/src/keybindings/useKeybinding.ts +0 -196
  1003. package/src/keybindings/useShortcutDisplay.ts +0 -59
  1004. package/src/keybindings/validate.ts +0 -498
  1005. package/src/main.tsx +0 -4684
  1006. package/src/memdir/findRelevantMemories.ts +0 -141
  1007. package/src/memdir/memdir.ts +0 -507
  1008. package/src/memdir/memoryAge.ts +0 -53
  1009. package/src/memdir/memoryScan.ts +0 -94
  1010. package/src/memdir/memoryShapeTelemetry.ts +0 -2
  1011. package/src/memdir/memoryTypes.ts +0 -271
  1012. package/src/memdir/paths.ts +0 -278
  1013. package/src/memdir/teamMemPaths.ts +0 -292
  1014. package/src/memdir/teamMemPrompts.ts +0 -100
  1015. package/src/migrations/migrateAutoUpdatesToSettings.ts +0 -61
  1016. package/src/migrations/migrateBypassPermissionsAcceptedToSettings.ts +0 -40
  1017. package/src/migrations/migrateEnableAllProjectMcpServersToSettings.ts +0 -118
  1018. package/src/migrations/migrateFennecToOpus.ts +0 -45
  1019. package/src/migrations/migrateLegacyOpusToCurrent.ts +0 -57
  1020. package/src/migrations/migrateOpusToOpus1m.ts +0 -43
  1021. package/src/migrations/migrateReplBridgeEnabledToRemoteControlAtStartup.ts +0 -22
  1022. package/src/migrations/migrateSonnet1mToSonnet45.ts +0 -48
  1023. package/src/migrations/migrateSonnet45ToSonnet46.ts +0 -67
  1024. package/src/migrations/resetAutoModeOptInForDefaultOffer.ts +0 -51
  1025. package/src/migrations/resetProToOpusDefault.ts +0 -51
  1026. package/src/moreright/useMoreRight.tsx +0 -26
  1027. package/src/native-ts/color-diff/index.ts +0 -1001
  1028. package/src/native-ts/file-index/index.ts +0 -370
  1029. package/src/native-ts/yoga-layout/enums.ts +0 -134
  1030. package/src/native-ts/yoga-layout/index.ts +0 -2578
  1031. package/src/outputStyles/loadOutputStylesDir.ts +0 -98
  1032. package/src/plugins/builtinPlugins.ts +0 -159
  1033. package/src/plugins/bundled/index.ts +0 -23
  1034. package/src/proactive/index.ts +0 -1
  1035. package/src/proactive/useProactive.ts +0 -1
  1036. package/src/projectOnboardingState.ts +0 -83
  1037. package/src/query/config.ts +0 -46
  1038. package/src/query/deps.ts +0 -33
  1039. package/src/query/stopHooks.ts +0 -473
  1040. package/src/query/tokenBudget.ts +0 -93
  1041. package/src/query/transitions.ts +0 -2
  1042. package/src/query.ts +0 -1729
  1043. package/src/remote/RemoteSessionManager.ts +0 -343
  1044. package/src/remote/SessionsWebSocket.ts +0 -404
  1045. package/src/remote/remotePermissionBridge.ts +0 -78
  1046. package/src/remote/sdkMessageAdapter.ts +0 -302
  1047. package/src/replLauncher.tsx +0 -23
  1048. package/src/schemas/hooks.ts +0 -222
  1049. package/src/screens/Doctor.tsx +0 -575
  1050. package/src/screens/REPL.tsx +0 -5006
  1051. package/src/screens/ResumeConversation.tsx +0 -399
  1052. package/src/self-hosted-runner/main.ts +0 -2
  1053. package/src/server/backends/dangerousBackend.ts +0 -2
  1054. package/src/server/connectHeadless.ts +0 -2
  1055. package/src/server/createDirectConnectSession.ts +0 -88
  1056. package/src/server/directConnectManager.ts +0 -213
  1057. package/src/server/lockfile.ts +0 -2
  1058. package/src/server/parseConnectUrl.ts +0 -2
  1059. package/src/server/server.ts +0 -2
  1060. package/src/server/serverBanner.ts +0 -2
  1061. package/src/server/serverLog.ts +0 -2
  1062. package/src/server/sessionManager.ts +0 -2
  1063. package/src/server/types.ts +0 -57
  1064. package/src/services/AgentSummary/agentSummary.ts +0 -179
  1065. package/src/services/MagicDocs/magicDocs.ts +0 -254
  1066. package/src/services/MagicDocs/prompts.ts +0 -127
  1067. package/src/services/PromptSuggestion/promptSuggestion.ts +0 -523
  1068. package/src/services/PromptSuggestion/speculation.ts +0 -991
  1069. package/src/services/SessionMemory/prompts.ts +0 -324
  1070. package/src/services/SessionMemory/sessionMemory.ts +0 -495
  1071. package/src/services/SessionMemory/sessionMemoryUtils.ts +0 -207
  1072. package/src/services/analytics/config.ts +0 -38
  1073. package/src/services/analytics/datadog.ts +0 -307
  1074. package/src/services/analytics/firstPartyEventLogger.ts +0 -449
  1075. package/src/services/analytics/firstPartyEventLoggingExporter.ts +0 -806
  1076. package/src/services/analytics/growthbook.ts +0 -1155
  1077. package/src/services/analytics/index.ts +0 -173
  1078. package/src/services/analytics/metadata.ts +0 -973
  1079. package/src/services/analytics/sink.ts +0 -114
  1080. package/src/services/analytics/sinkKillswitch.ts +0 -25
  1081. package/src/services/api/adminRequests.ts +0 -119
  1082. package/src/services/api/bootstrap.ts +0 -141
  1083. package/src/services/api/claude.ts +0 -3419
  1084. package/src/services/api/client.ts +0 -389
  1085. package/src/services/api/dumpPrompts.ts +0 -226
  1086. package/src/services/api/emptyUsage.ts +0 -22
  1087. package/src/services/api/errorUtils.ts +0 -260
  1088. package/src/services/api/errors.ts +0 -1205
  1089. package/src/services/api/filesApi.ts +0 -748
  1090. package/src/services/api/firstTokenDate.ts +0 -60
  1091. package/src/services/api/grove.ts +0 -357
  1092. package/src/services/api/logging.ts +0 -788
  1093. package/src/services/api/metricsOptOut.ts +0 -159
  1094. package/src/services/api/overageCreditGrant.ts +0 -137
  1095. package/src/services/api/promptCacheBreakDetection.ts +0 -727
  1096. package/src/services/api/referral.ts +0 -281
  1097. package/src/services/api/sessionIngress.ts +0 -514
  1098. package/src/services/api/ultrareviewQuota.ts +0 -38
  1099. package/src/services/api/usage.ts +0 -63
  1100. package/src/services/api/withRetry.ts +0 -818
  1101. package/src/services/autoDream/autoDream.ts +0 -324
  1102. package/src/services/autoDream/config.ts +0 -21
  1103. package/src/services/autoDream/consolidationLock.ts +0 -140
  1104. package/src/services/autoDream/consolidationPrompt.ts +0 -65
  1105. package/src/services/autoDream/dream.ts +0 -1
  1106. package/src/services/awaySummary.ts +0 -74
  1107. package/src/services/claudeAiLimits.ts +0 -515
  1108. package/src/services/claudeAiLimitsHook.ts +0 -23
  1109. package/src/services/compact/apiMicrocompact.ts +0 -153
  1110. package/src/services/compact/autoCompact.ts +0 -351
  1111. package/src/services/compact/cachedMCConfig.ts +0 -2
  1112. package/src/services/compact/cachedMicrocompact.ts +0 -2
  1113. package/src/services/compact/compact.ts +0 -1705
  1114. package/src/services/compact/compactWarningHook.ts +0 -16
  1115. package/src/services/compact/compactWarningState.ts +0 -18
  1116. package/src/services/compact/grouping.ts +0 -63
  1117. package/src/services/compact/microCompact.ts +0 -530
  1118. package/src/services/compact/postCompactCleanup.ts +0 -77
  1119. package/src/services/compact/prompt.ts +0 -374
  1120. package/src/services/compact/reactiveCompact.ts +0 -2
  1121. package/src/services/compact/sessionMemoryCompact.ts +0 -630
  1122. package/src/services/compact/snipCompact.ts +0 -1
  1123. package/src/services/compact/snipProjection.ts +0 -2
  1124. package/src/services/compact/timeBasedMCConfig.ts +0 -43
  1125. package/src/services/contextCollapse/index.ts +0 -2
  1126. package/src/services/contextCollapse/operations.ts +0 -2
  1127. package/src/services/contextCollapse/persist.ts +0 -2
  1128. package/src/services/diagnosticTracking.ts +0 -397
  1129. package/src/services/extractMemories/extractMemories.ts +0 -615
  1130. package/src/services/extractMemories/prompts.ts +0 -154
  1131. package/src/services/internalLogging.ts +0 -90
  1132. package/src/services/lsp/LSPClient.ts +0 -447
  1133. package/src/services/lsp/LSPDiagnosticRegistry.ts +0 -386
  1134. package/src/services/lsp/LSPServerInstance.ts +0 -511
  1135. package/src/services/lsp/LSPServerManager.ts +0 -420
  1136. package/src/services/lsp/config.ts +0 -79
  1137. package/src/services/lsp/manager.ts +0 -289
  1138. package/src/services/lsp/passiveFeedback.ts +0 -328
  1139. package/src/services/lsp/types.ts +0 -3
  1140. package/src/services/mcp/InProcessTransport.ts +0 -63
  1141. package/src/services/mcp/MCPConnectionManager.tsx +0 -73
  1142. package/src/services/mcp/SdkControlTransport.ts +0 -136
  1143. package/src/services/mcp/auth.ts +0 -2465
  1144. package/src/services/mcp/channelAllowlist.ts +0 -76
  1145. package/src/services/mcp/channelNotification.ts +0 -316
  1146. package/src/services/mcp/channelPermissions.ts +0 -240
  1147. package/src/services/mcp/claudeai.ts +0 -164
  1148. package/src/services/mcp/client.ts +0 -3348
  1149. package/src/services/mcp/config.ts +0 -1578
  1150. package/src/services/mcp/elicitationHandler.ts +0 -313
  1151. package/src/services/mcp/envExpansion.ts +0 -38
  1152. package/src/services/mcp/headersHelper.ts +0 -138
  1153. package/src/services/mcp/mcpStringUtils.ts +0 -106
  1154. package/src/services/mcp/normalization.ts +0 -23
  1155. package/src/services/mcp/oauthPort.ts +0 -78
  1156. package/src/services/mcp/officialRegistry.ts +0 -72
  1157. package/src/services/mcp/types.ts +0 -258
  1158. package/src/services/mcp/useManageMCPConnections.ts +0 -1141
  1159. package/src/services/mcp/utils.ts +0 -575
  1160. package/src/services/mcp/vscodeSdkMcp.ts +0 -112
  1161. package/src/services/mcp/xaa.ts +0 -511
  1162. package/src/services/mcp/xaaIdpLogin.ts +0 -487
  1163. package/src/services/mcpServerApproval.tsx +0 -41
  1164. package/src/services/mockRateLimits.ts +0 -882
  1165. package/src/services/notifier.ts +0 -156
  1166. package/src/services/oauth/auth-code-listener.ts +0 -211
  1167. package/src/services/oauth/client.ts +0 -566
  1168. package/src/services/oauth/crypto.ts +0 -23
  1169. package/src/services/oauth/getOauthProfile.ts +0 -53
  1170. package/src/services/oauth/index.ts +0 -198
  1171. package/src/services/oauth/types.ts +0 -7
  1172. package/src/services/plugins/PluginInstallationManager.ts +0 -184
  1173. package/src/services/plugins/pluginCliCommands.ts +0 -344
  1174. package/src/services/plugins/pluginOperations.ts +0 -1088
  1175. package/src/services/policyLimits/index.ts +0 -663
  1176. package/src/services/policyLimits/types.ts +0 -27
  1177. package/src/services/preventSleep.ts +0 -165
  1178. package/src/services/rateLimitMessages.ts +0 -344
  1179. package/src/services/rateLimitMocking.ts +0 -144
  1180. package/src/services/remoteManagedSettings/index.ts +0 -638
  1181. package/src/services/remoteManagedSettings/securityCheck.tsx +0 -74
  1182. package/src/services/remoteManagedSettings/syncCache.ts +0 -112
  1183. package/src/services/remoteManagedSettings/syncCacheState.ts +0 -96
  1184. package/src/services/remoteManagedSettings/types.ts +0 -31
  1185. package/src/services/sessionTranscript/sessionTranscript.ts +0 -2
  1186. package/src/services/settingsSync/index.ts +0 -581
  1187. package/src/services/settingsSync/types.ts +0 -67
  1188. package/src/services/skillSearch/featureCheck.ts +0 -2
  1189. package/src/services/skillSearch/localSearch.ts +0 -2
  1190. package/src/services/skillSearch/prefetch.ts +0 -2
  1191. package/src/services/skillSearch/remoteSkillLoader.ts +0 -2
  1192. package/src/services/skillSearch/remoteSkillState.ts +0 -2
  1193. package/src/services/skillSearch/signals.ts +0 -1
  1194. package/src/services/skillSearch/telemetry.ts +0 -2
  1195. package/src/services/teamMemorySync/index.ts +0 -1256
  1196. package/src/services/teamMemorySync/secretScanner.ts +0 -324
  1197. package/src/services/teamMemorySync/teamMemSecretGuard.ts +0 -44
  1198. package/src/services/teamMemorySync/types.ts +0 -156
  1199. package/src/services/teamMemorySync/watcher.ts +0 -387
  1200. package/src/services/tips/tipHistory.ts +0 -17
  1201. package/src/services/tips/tipRegistry.ts +0 -686
  1202. package/src/services/tips/tipScheduler.ts +0 -58
  1203. package/src/services/tips/types.ts +0 -5
  1204. package/src/services/tokenEstimation.ts +0 -495
  1205. package/src/services/toolUseSummary/toolUseSummaryGenerator.ts +0 -112
  1206. package/src/services/tools/StreamingToolExecutor.ts +0 -530
  1207. package/src/services/tools/toolExecution.ts +0 -1745
  1208. package/src/services/tools/toolHooks.ts +0 -650
  1209. package/src/services/tools/toolOrchestration.ts +0 -188
  1210. package/src/services/vcr.ts +0 -406
  1211. package/src/services/voice.ts +0 -525
  1212. package/src/services/voiceKeyterms.ts +0 -106
  1213. package/src/services/voiceStreamSTT.ts +0 -544
  1214. package/src/setup.ts +0 -477
  1215. package/src/shims/bun-bundle.ts +0 -18
  1216. package/src/shims/macro.ts +0 -12
  1217. package/src/skills/bundled/batch.ts +0 -124
  1218. package/src/skills/bundled/claude-api/SKILL.md +0 -1
  1219. package/src/skills/bundled/claude-api/SKILL.md.ts +0 -1
  1220. package/src/skills/bundled/claude-api/csharp/claude-api.md +0 -1
  1221. package/src/skills/bundled/claude-api/csharp/claude-api.md.ts +0 -1
  1222. package/src/skills/bundled/claude-api/curl/examples.md +0 -1
  1223. package/src/skills/bundled/claude-api/curl/examples.md.ts +0 -1
  1224. package/src/skills/bundled/claude-api/go/claude-api.md +0 -1
  1225. package/src/skills/bundled/claude-api/go/claude-api.md.ts +0 -1
  1226. package/src/skills/bundled/claude-api/java/claude-api.md +0 -1
  1227. package/src/skills/bundled/claude-api/java/claude-api.md.ts +0 -1
  1228. package/src/skills/bundled/claude-api/php/claude-api.md +0 -1
  1229. package/src/skills/bundled/claude-api/php/claude-api.md.ts +0 -1
  1230. package/src/skills/bundled/claude-api/python/agent-sdk/README.md +0 -1
  1231. package/src/skills/bundled/claude-api/python/agent-sdk/README.md.ts +0 -1
  1232. package/src/skills/bundled/claude-api/python/agent-sdk/patterns.md +0 -1
  1233. package/src/skills/bundled/claude-api/python/agent-sdk/patterns.md.ts +0 -1
  1234. package/src/skills/bundled/claude-api/python/claude-api/README.md +0 -1
  1235. package/src/skills/bundled/claude-api/python/claude-api/README.md.ts +0 -1
  1236. package/src/skills/bundled/claude-api/python/claude-api/batches.md +0 -1
  1237. package/src/skills/bundled/claude-api/python/claude-api/batches.md.ts +0 -1
  1238. package/src/skills/bundled/claude-api/python/claude-api/files-api.md +0 -1
  1239. package/src/skills/bundled/claude-api/python/claude-api/files-api.md.ts +0 -1
  1240. package/src/skills/bundled/claude-api/python/claude-api/streaming.md +0 -1
  1241. package/src/skills/bundled/claude-api/python/claude-api/streaming.md.ts +0 -1
  1242. package/src/skills/bundled/claude-api/python/claude-api/tool-use.md +0 -1
  1243. package/src/skills/bundled/claude-api/python/claude-api/tool-use.md.ts +0 -1
  1244. package/src/skills/bundled/claude-api/ruby/claude-api.md +0 -1
  1245. package/src/skills/bundled/claude-api/ruby/claude-api.md.ts +0 -1
  1246. package/src/skills/bundled/claude-api/shared/error-codes.md +0 -1
  1247. package/src/skills/bundled/claude-api/shared/error-codes.md.ts +0 -1
  1248. package/src/skills/bundled/claude-api/shared/live-sources.md +0 -1
  1249. package/src/skills/bundled/claude-api/shared/live-sources.md.ts +0 -1
  1250. package/src/skills/bundled/claude-api/shared/models.md +0 -1
  1251. package/src/skills/bundled/claude-api/shared/models.md.ts +0 -1
  1252. package/src/skills/bundled/claude-api/shared/prompt-caching.md +0 -1
  1253. package/src/skills/bundled/claude-api/shared/prompt-caching.md.ts +0 -1
  1254. package/src/skills/bundled/claude-api/shared/tool-use-concepts.md +0 -1
  1255. package/src/skills/bundled/claude-api/shared/tool-use-concepts.md.ts +0 -1
  1256. package/src/skills/bundled/claude-api/typescript/agent-sdk/README.md +0 -1
  1257. package/src/skills/bundled/claude-api/typescript/agent-sdk/README.md.ts +0 -1
  1258. package/src/skills/bundled/claude-api/typescript/agent-sdk/patterns.md +0 -1
  1259. package/src/skills/bundled/claude-api/typescript/agent-sdk/patterns.md.ts +0 -1
  1260. package/src/skills/bundled/claude-api/typescript/claude-api/README.md +0 -1
  1261. package/src/skills/bundled/claude-api/typescript/claude-api/README.md.ts +0 -1
  1262. package/src/skills/bundled/claude-api/typescript/claude-api/batches.md +0 -1
  1263. package/src/skills/bundled/claude-api/typescript/claude-api/batches.md.ts +0 -1
  1264. package/src/skills/bundled/claude-api/typescript/claude-api/files-api.md +0 -1
  1265. package/src/skills/bundled/claude-api/typescript/claude-api/files-api.md.ts +0 -1
  1266. package/src/skills/bundled/claude-api/typescript/claude-api/streaming.md +0 -1
  1267. package/src/skills/bundled/claude-api/typescript/claude-api/streaming.md.ts +0 -1
  1268. package/src/skills/bundled/claude-api/typescript/claude-api/tool-use.md +0 -1
  1269. package/src/skills/bundled/claude-api/typescript/claude-api/tool-use.md.ts +0 -1
  1270. package/src/skills/bundled/claudeApi.ts +0 -196
  1271. package/src/skills/bundled/claudeApiContent.ts +0 -75
  1272. package/src/skills/bundled/claudeInChrome.ts +0 -34
  1273. package/src/skills/bundled/debug.ts +0 -103
  1274. package/src/skills/bundled/dream.ts +0 -1
  1275. package/src/skills/bundled/hunter.ts +0 -1
  1276. package/src/skills/bundled/index.ts +0 -79
  1277. package/src/skills/bundled/keybindings.ts +0 -339
  1278. package/src/skills/bundled/loop.ts +0 -92
  1279. package/src/skills/bundled/loremIpsum.ts +0 -282
  1280. package/src/skills/bundled/remember.ts +0 -82
  1281. package/src/skills/bundled/runSkillGenerator.ts +0 -1
  1282. package/src/skills/bundled/scheduleRemoteAgents.ts +0 -447
  1283. package/src/skills/bundled/simplify.ts +0 -69
  1284. package/src/skills/bundled/skillify.ts +0 -197
  1285. package/src/skills/bundled/stuck.ts +0 -79
  1286. package/src/skills/bundled/updateConfig.ts +0 -475
  1287. package/src/skills/bundled/verify/SKILL.md +0 -1
  1288. package/src/skills/bundled/verify/SKILL.md.ts +0 -1
  1289. package/src/skills/bundled/verify/examples/cli.md +0 -1
  1290. package/src/skills/bundled/verify/examples/cli.md.ts +0 -1
  1291. package/src/skills/bundled/verify/examples/server.md +0 -1
  1292. package/src/skills/bundled/verify/examples/server.md.ts +0 -1
  1293. package/src/skills/bundled/verify.ts +0 -30
  1294. package/src/skills/bundled/verifyContent.ts +0 -13
  1295. package/src/skills/bundledSkills.ts +0 -220
  1296. package/src/skills/loadSkillsDir.ts +0 -1086
  1297. package/src/skills/mcpSkillBuilders.ts +0 -44
  1298. package/src/skills/mcpSkills.ts +0 -2
  1299. package/src/ssh/SSHSessionManager.ts +0 -1
  1300. package/src/ssh/createSSHSession.ts +0 -1
  1301. package/src/state/AppState.tsx +0 -200
  1302. package/src/state/AppStateStore.ts +0 -569
  1303. package/src/state/onChangeAppState.ts +0 -171
  1304. package/src/state/selectors.ts +0 -76
  1305. package/src/state/store.ts +0 -34
  1306. package/src/state/teammateViewHelpers.ts +0 -141
  1307. package/src/tasks/DreamTask/DreamTask.ts +0 -157
  1308. package/src/tasks/InProcessTeammateTask/InProcessTeammateTask.tsx +0 -126
  1309. package/src/tasks/InProcessTeammateTask/types.ts +0 -121
  1310. package/src/tasks/LocalAgentTask/LocalAgentTask.tsx +0 -683
  1311. package/src/tasks/LocalMainSessionTask.ts +0 -479
  1312. package/src/tasks/LocalShellTask/LocalShellTask.tsx +0 -523
  1313. package/src/tasks/LocalShellTask/guards.ts +0 -41
  1314. package/src/tasks/LocalShellTask/killShellTasks.ts +0 -76
  1315. package/src/tasks/LocalWorkflowTask/LocalWorkflowTask.ts +0 -1
  1316. package/src/tasks/MonitorMcpTask/MonitorMcpTask.ts +0 -1
  1317. package/src/tasks/RemoteAgentTask/RemoteAgentTask.tsx +0 -856
  1318. package/src/tasks/pillLabel.ts +0 -82
  1319. package/src/tasks/stopTask.ts +0 -100
  1320. package/src/tasks/types.ts +0 -46
  1321. package/src/tasks.ts +0 -39
  1322. package/src/tools/AgentTool/AgentTool.tsx +0 -1398
  1323. package/src/tools/AgentTool/UI.tsx +0 -872
  1324. package/src/tools/AgentTool/agentColorManager.ts +0 -66
  1325. package/src/tools/AgentTool/agentDisplay.ts +0 -104
  1326. package/src/tools/AgentTool/agentMemory.ts +0 -177
  1327. package/src/tools/AgentTool/agentMemorySnapshot.ts +0 -197
  1328. package/src/tools/AgentTool/agentToolUtils.ts +0 -686
  1329. package/src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts +0 -205
  1330. package/src/tools/AgentTool/built-in/exploreAgent.ts +0 -87
  1331. package/src/tools/AgentTool/built-in/generalPurposeAgent.ts +0 -34
  1332. package/src/tools/AgentTool/built-in/planAgent.ts +0 -92
  1333. package/src/tools/AgentTool/built-in/statuslineSetup.ts +0 -144
  1334. package/src/tools/AgentTool/built-in/verificationAgent.ts +0 -152
  1335. package/src/tools/AgentTool/built-in/warpGrepAgent.ts +0 -67
  1336. package/src/tools/AgentTool/builtInAgents.ts +0 -73
  1337. package/src/tools/AgentTool/constants.ts +0 -12
  1338. package/src/tools/AgentTool/forkSubagent.ts +0 -210
  1339. package/src/tools/AgentTool/loadAgentsDir.ts +0 -755
  1340. package/src/tools/AgentTool/prompt.ts +0 -288
  1341. package/src/tools/AgentTool/resumeAgent.ts +0 -265
  1342. package/src/tools/AgentTool/runAgent.ts +0 -973
  1343. package/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +0 -266
  1344. package/src/tools/AskUserQuestionTool/prompt.ts +0 -44
  1345. package/src/tools/BashTool/BashTool.tsx +0 -1144
  1346. package/src/tools/BashTool/BashToolResultMessage.tsx +0 -191
  1347. package/src/tools/BashTool/UI.tsx +0 -185
  1348. package/src/tools/BashTool/bashCommandHelpers.ts +0 -265
  1349. package/src/tools/BashTool/bashPermissions.ts +0 -2621
  1350. package/src/tools/BashTool/bashSecurity.ts +0 -2592
  1351. package/src/tools/BashTool/commandSemantics.ts +0 -140
  1352. package/src/tools/BashTool/commentLabel.ts +0 -13
  1353. package/src/tools/BashTool/destructiveCommandWarning.ts +0 -102
  1354. package/src/tools/BashTool/modeValidation.ts +0 -115
  1355. package/src/tools/BashTool/pathValidation.ts +0 -1303
  1356. package/src/tools/BashTool/prompt.ts +0 -369
  1357. package/src/tools/BashTool/readOnlyValidation.ts +0 -1990
  1358. package/src/tools/BashTool/sedEditParser.ts +0 -322
  1359. package/src/tools/BashTool/sedValidation.ts +0 -684
  1360. package/src/tools/BashTool/shouldUseSandbox.ts +0 -153
  1361. package/src/tools/BashTool/toolName.ts +0 -2
  1362. package/src/tools/BashTool/utils.ts +0 -223
  1363. package/src/tools/BriefTool/BriefTool.ts +0 -204
  1364. package/src/tools/BriefTool/UI.tsx +0 -101
  1365. package/src/tools/BriefTool/attachments.ts +0 -110
  1366. package/src/tools/BriefTool/prompt.ts +0 -22
  1367. package/src/tools/BriefTool/upload.ts +0 -174
  1368. package/src/tools/ConfigTool/ConfigTool.ts +0 -467
  1369. package/src/tools/ConfigTool/UI.tsx +0 -38
  1370. package/src/tools/ConfigTool/constants.ts +0 -1
  1371. package/src/tools/ConfigTool/prompt.ts +0 -93
  1372. package/src/tools/ConfigTool/supportedSettings.ts +0 -211
  1373. package/src/tools/CtxInspectTool/CtxInspectTool.ts +0 -1
  1374. package/src/tools/DiscoverSkillsTool/prompt.ts +0 -2
  1375. package/src/tools/EnterPlanModeTool/EnterPlanModeTool.ts +0 -126
  1376. package/src/tools/EnterPlanModeTool/UI.tsx +0 -33
  1377. package/src/tools/EnterPlanModeTool/constants.ts +0 -1
  1378. package/src/tools/EnterPlanModeTool/prompt.ts +0 -170
  1379. package/src/tools/EnterWorktreeTool/EnterWorktreeTool.ts +0 -127
  1380. package/src/tools/EnterWorktreeTool/UI.tsx +0 -20
  1381. package/src/tools/EnterWorktreeTool/constants.ts +0 -1
  1382. package/src/tools/EnterWorktreeTool/prompt.ts +0 -30
  1383. package/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts +0 -493
  1384. package/src/tools/ExitPlanModeTool/UI.tsx +0 -82
  1385. package/src/tools/ExitPlanModeTool/constants.ts +0 -2
  1386. package/src/tools/ExitPlanModeTool/prompt.ts +0 -29
  1387. package/src/tools/ExitWorktreeTool/ExitWorktreeTool.ts +0 -329
  1388. package/src/tools/ExitWorktreeTool/UI.tsx +0 -25
  1389. package/src/tools/ExitWorktreeTool/constants.ts +0 -1
  1390. package/src/tools/ExitWorktreeTool/prompt.ts +0 -32
  1391. package/src/tools/FileEditTool/FileEditTool.ts +0 -625
  1392. package/src/tools/FileEditTool/UI.tsx +0 -289
  1393. package/src/tools/FileEditTool/constants.ts +0 -11
  1394. package/src/tools/FileEditTool/prompt.ts +0 -28
  1395. package/src/tools/FileEditTool/types.ts +0 -85
  1396. package/src/tools/FileEditTool/utils.ts +0 -775
  1397. package/src/tools/FileReadTool/FileReadTool.ts +0 -1183
  1398. package/src/tools/FileReadTool/UI.tsx +0 -185
  1399. package/src/tools/FileReadTool/imageProcessor.ts +0 -94
  1400. package/src/tools/FileReadTool/limits.ts +0 -92
  1401. package/src/tools/FileReadTool/prompt.ts +0 -49
  1402. package/src/tools/FileWriteTool/FileWriteTool.ts +0 -434
  1403. package/src/tools/FileWriteTool/UI.tsx +0 -405
  1404. package/src/tools/FileWriteTool/prompt.ts +0 -18
  1405. package/src/tools/GlobTool/GlobTool.ts +0 -198
  1406. package/src/tools/GlobTool/UI.tsx +0 -63
  1407. package/src/tools/GlobTool/prompt.ts +0 -7
  1408. package/src/tools/GrepTool/GrepTool.ts +0 -577
  1409. package/src/tools/GrepTool/UI.tsx +0 -201
  1410. package/src/tools/GrepTool/prompt.ts +0 -18
  1411. package/src/tools/LSPTool/LSPTool.ts +0 -860
  1412. package/src/tools/LSPTool/UI.tsx +0 -228
  1413. package/src/tools/LSPTool/formatters.ts +0 -592
  1414. package/src/tools/LSPTool/prompt.ts +0 -21
  1415. package/src/tools/LSPTool/schemas.ts +0 -215
  1416. package/src/tools/LSPTool/symbolContext.ts +0 -90
  1417. package/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +0 -123
  1418. package/src/tools/ListMcpResourcesTool/UI.tsx +0 -29
  1419. package/src/tools/ListMcpResourcesTool/prompt.ts +0 -20
  1420. package/src/tools/ListPeersTool/ListPeersTool.ts +0 -1
  1421. package/src/tools/MCPTool/MCPTool.ts +0 -77
  1422. package/src/tools/MCPTool/UI.tsx +0 -403
  1423. package/src/tools/MCPTool/classifyForCollapse.ts +0 -604
  1424. package/src/tools/MCPTool/prompt.ts +0 -3
  1425. package/src/tools/McpAuthTool/McpAuthTool.ts +0 -215
  1426. package/src/tools/MonitorTool/MonitorTool.ts +0 -2
  1427. package/src/tools/NotebookEditTool/NotebookEditTool.ts +0 -490
  1428. package/src/tools/NotebookEditTool/UI.tsx +0 -93
  1429. package/src/tools/NotebookEditTool/constants.ts +0 -2
  1430. package/src/tools/NotebookEditTool/prompt.ts +0 -3
  1431. package/src/tools/OverflowTestTool/OverflowTestTool.ts +0 -2
  1432. package/src/tools/PowerShellTool/PowerShellTool.tsx +0 -1001
  1433. package/src/tools/PowerShellTool/UI.tsx +0 -131
  1434. package/src/tools/PowerShellTool/clmTypes.ts +0 -211
  1435. package/src/tools/PowerShellTool/commandSemantics.ts +0 -142
  1436. package/src/tools/PowerShellTool/commonParameters.ts +0 -30
  1437. package/src/tools/PowerShellTool/destructiveCommandWarning.ts +0 -109
  1438. package/src/tools/PowerShellTool/gitSafety.ts +0 -176
  1439. package/src/tools/PowerShellTool/modeValidation.ts +0 -404
  1440. package/src/tools/PowerShellTool/pathValidation.ts +0 -2049
  1441. package/src/tools/PowerShellTool/powershellPermissions.ts +0 -1648
  1442. package/src/tools/PowerShellTool/powershellSecurity.ts +0 -1090
  1443. package/src/tools/PowerShellTool/prompt.ts +0 -145
  1444. package/src/tools/PowerShellTool/readOnlyValidation.ts +0 -1823
  1445. package/src/tools/PowerShellTool/toolName.ts +0 -2
  1446. package/src/tools/PushNotificationTool/PushNotificationTool.ts +0 -1
  1447. package/src/tools/REPLTool/REPLTool.ts +0 -1
  1448. package/src/tools/REPLTool/constants.ts +0 -46
  1449. package/src/tools/REPLTool/primitiveTools.ts +0 -39
  1450. package/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +0 -158
  1451. package/src/tools/ReadMcpResourceTool/UI.tsx +0 -37
  1452. package/src/tools/ReadMcpResourceTool/prompt.ts +0 -16
  1453. package/src/tools/RemoteTriggerTool/RemoteTriggerTool.ts +0 -161
  1454. package/src/tools/RemoteTriggerTool/UI.tsx +0 -17
  1455. package/src/tools/RemoteTriggerTool/prompt.ts +0 -15
  1456. package/src/tools/ReviewArtifactTool/ReviewArtifactTool.ts +0 -2
  1457. package/src/tools/ScheduleCronTool/CronCreateTool.ts +0 -157
  1458. package/src/tools/ScheduleCronTool/CronDeleteTool.ts +0 -95
  1459. package/src/tools/ScheduleCronTool/CronListTool.ts +0 -97
  1460. package/src/tools/ScheduleCronTool/UI.tsx +0 -60
  1461. package/src/tools/ScheduleCronTool/prompt.ts +0 -135
  1462. package/src/tools/SendMessageTool/SendMessageTool.ts +0 -917
  1463. package/src/tools/SendMessageTool/UI.tsx +0 -31
  1464. package/src/tools/SendMessageTool/constants.ts +0 -1
  1465. package/src/tools/SendMessageTool/prompt.ts +0 -49
  1466. package/src/tools/SendUserFileTool/SendUserFileTool.ts +0 -1
  1467. package/src/tools/SendUserFileTool/prompt.ts +0 -2
  1468. package/src/tools/SkillTool/SkillTool.ts +0 -1108
  1469. package/src/tools/SkillTool/UI.tsx +0 -128
  1470. package/src/tools/SkillTool/constants.ts +0 -1
  1471. package/src/tools/SkillTool/prompt.ts +0 -241
  1472. package/src/tools/SleepTool/SleepTool.ts +0 -1
  1473. package/src/tools/SleepTool/prompt.ts +0 -17
  1474. package/src/tools/SnipTool/SnipTool.ts +0 -1
  1475. package/src/tools/SnipTool/prompt.ts +0 -2
  1476. package/src/tools/SubscribePRTool/SubscribePRTool.ts +0 -1
  1477. package/src/tools/SuggestBackgroundPRTool/SuggestBackgroundPRTool.ts +0 -1
  1478. package/src/tools/SyntheticOutputTool/SyntheticOutputTool.ts +0 -163
  1479. package/src/tools/TaskCreateTool/TaskCreateTool.ts +0 -138
  1480. package/src/tools/TaskCreateTool/constants.ts +0 -1
  1481. package/src/tools/TaskCreateTool/prompt.ts +0 -56
  1482. package/src/tools/TaskGetTool/TaskGetTool.ts +0 -128
  1483. package/src/tools/TaskGetTool/constants.ts +0 -1
  1484. package/src/tools/TaskGetTool/prompt.ts +0 -24
  1485. package/src/tools/TaskListTool/TaskListTool.ts +0 -116
  1486. package/src/tools/TaskListTool/constants.ts +0 -1
  1487. package/src/tools/TaskListTool/prompt.ts +0 -49
  1488. package/src/tools/TaskOutputTool/TaskOutputTool.tsx +0 -584
  1489. package/src/tools/TaskOutputTool/constants.ts +0 -1
  1490. package/src/tools/TaskStopTool/TaskStopTool.ts +0 -131
  1491. package/src/tools/TaskStopTool/UI.tsx +0 -41
  1492. package/src/tools/TaskStopTool/prompt.ts +0 -8
  1493. package/src/tools/TaskUpdateTool/TaskUpdateTool.ts +0 -406
  1494. package/src/tools/TaskUpdateTool/constants.ts +0 -1
  1495. package/src/tools/TaskUpdateTool/prompt.ts +0 -77
  1496. package/src/tools/TeamCreateTool/TeamCreateTool.ts +0 -240
  1497. package/src/tools/TeamCreateTool/UI.tsx +0 -6
  1498. package/src/tools/TeamCreateTool/constants.ts +0 -1
  1499. package/src/tools/TeamCreateTool/prompt.ts +0 -113
  1500. package/src/tools/TeamDeleteTool/TeamDeleteTool.ts +0 -139
  1501. package/src/tools/TeamDeleteTool/UI.tsx +0 -20
  1502. package/src/tools/TeamDeleteTool/constants.ts +0 -1
  1503. package/src/tools/TeamDeleteTool/prompt.ts +0 -16
  1504. package/src/tools/TerminalCaptureTool/TerminalCaptureTool.ts +0 -1
  1505. package/src/tools/TerminalCaptureTool/prompt.ts +0 -2
  1506. package/src/tools/TodoWriteTool/TodoWriteTool.ts +0 -115
  1507. package/src/tools/TodoWriteTool/constants.ts +0 -1
  1508. package/src/tools/TodoWriteTool/prompt.ts +0 -184
  1509. package/src/tools/ToolSearchTool/ToolSearchTool.ts +0 -471
  1510. package/src/tools/ToolSearchTool/constants.ts +0 -1
  1511. package/src/tools/ToolSearchTool/prompt.ts +0 -121
  1512. package/src/tools/TungstenTool/TungstenLiveMonitor.ts +0 -3
  1513. package/src/tools/TungstenTool/TungstenLiveMonitor.tsx +0 -6
  1514. package/src/tools/TungstenTool/TungstenTool.ts +0 -26
  1515. package/src/tools/VerifyPlanExecutionTool/VerifyPlanExecutionTool.ts +0 -1
  1516. package/src/tools/VerifyPlanExecutionTool/constants.ts +0 -2
  1517. package/src/tools/WarpGrepTool/WarpGrepTool.ts +0 -106
  1518. package/src/tools/WebBrowserTool/WebBrowserPanel.ts +0 -2
  1519. package/src/tools/WebBrowserTool/WebBrowserTool.ts +0 -1
  1520. package/src/tools/WebFetchTool/UI.tsx +0 -72
  1521. package/src/tools/WebFetchTool/WebFetchTool.ts +0 -318
  1522. package/src/tools/WebFetchTool/preapproved.ts +0 -166
  1523. package/src/tools/WebFetchTool/prompt.ts +0 -46
  1524. package/src/tools/WebFetchTool/utils.ts +0 -530
  1525. package/src/tools/WebSearchTool/UI.tsx +0 -101
  1526. package/src/tools/WebSearchTool/WebSearchTool.ts +0 -435
  1527. package/src/tools/WebSearchTool/prompt.ts +0 -34
  1528. package/src/tools/WorkflowTool/WorkflowPermissionRequest.ts +0 -2
  1529. package/src/tools/WorkflowTool/WorkflowTool.ts +0 -2
  1530. package/src/tools/WorkflowTool/bundled/index.ts +0 -1
  1531. package/src/tools/WorkflowTool/constants.ts +0 -1
  1532. package/src/tools/WorkflowTool/createWorkflowCommand.ts +0 -2
  1533. package/src/tools/shared/gitOperationTracking.ts +0 -277
  1534. package/src/tools/shared/spawnMultiAgent.ts +0 -1093
  1535. package/src/tools/testing/TestingPermissionTool.tsx +0 -74
  1536. package/src/tools/utils.ts +0 -40
  1537. package/src/tools.ts +0 -394
  1538. package/src/types/command.ts +0 -216
  1539. package/src/types/connectorText.ts +0 -3
  1540. package/src/types/declarations/bun-globals.d.ts +0 -19
  1541. package/src/types/declarations/external-modules.d.ts +0 -120
  1542. package/src/types/declarations/react-compiler.d.ts +0 -3
  1543. package/src/types/fileSuggestion.ts +0 -1
  1544. package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +0 -865
  1545. package/src/types/generated/events_mono/common/v1/auth.ts +0 -100
  1546. package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +0 -223
  1547. package/src/types/generated/google/protobuf/timestamp.ts +0 -187
  1548. package/src/types/hooks.ts +0 -290
  1549. package/src/types/ids.ts +0 -44
  1550. package/src/types/logs.ts +0 -330
  1551. package/src/types/message.ts +0 -40
  1552. package/src/types/messageQueueTypes.ts +0 -2
  1553. package/src/types/notebook.ts +0 -7
  1554. package/src/types/permissions.ts +0 -441
  1555. package/src/types/plugin.ts +0 -363
  1556. package/src/types/statusLine.ts +0 -1
  1557. package/src/types/textInputTypes.ts +0 -387
  1558. package/src/types/tools.ts +0 -11
  1559. package/src/types/utils.ts +0 -2
  1560. package/src/upstreamproxy/relay.ts +0 -455
  1561. package/src/upstreamproxy/upstreamproxy.ts +0 -285
  1562. package/src/utils/CircularBuffer.ts +0 -84
  1563. package/src/utils/Cursor.ts +0 -1530
  1564. package/src/utils/QueryGuard.ts +0 -121
  1565. package/src/utils/Shell.ts +0 -474
  1566. package/src/utils/ShellCommand.ts +0 -465
  1567. package/src/utils/abortController.ts +0 -99
  1568. package/src/utils/activityManager.ts +0 -164
  1569. package/src/utils/advisor.ts +0 -145
  1570. package/src/utils/agentContext.ts +0 -178
  1571. package/src/utils/agentId.ts +0 -99
  1572. package/src/utils/agentSwarmsEnabled.ts +0 -44
  1573. package/src/utils/agenticSessionSearch.ts +0 -307
  1574. package/src/utils/analyzeContext.ts +0 -1382
  1575. package/src/utils/ansiToPng.ts +0 -334
  1576. package/src/utils/ansiToSvg.ts +0 -272
  1577. package/src/utils/api.ts +0 -718
  1578. package/src/utils/apiPreconnect.ts +0 -71
  1579. package/src/utils/appleTerminalBackup.ts +0 -124
  1580. package/src/utils/argumentSubstitution.ts +0 -145
  1581. package/src/utils/array.ts +0 -13
  1582. package/src/utils/asciicast.ts +0 -239
  1583. package/src/utils/attachments.ts +0 -3997
  1584. package/src/utils/attribution.ts +0 -393
  1585. package/src/utils/attributionHooks.ts +0 -2
  1586. package/src/utils/attributionTrailer.ts +0 -2
  1587. package/src/utils/auth.ts +0 -2002
  1588. package/src/utils/authFileDescriptor.ts +0 -196
  1589. package/src/utils/authPortable.ts +0 -19
  1590. package/src/utils/autoModeDenials.ts +0 -26
  1591. package/src/utils/autoRunIssue.tsx +0 -122
  1592. package/src/utils/autoUpdater.ts +0 -561
  1593. package/src/utils/aws.ts +0 -74
  1594. package/src/utils/awsAuthStatusManager.ts +0 -81
  1595. package/src/utils/background/remote/preconditions.ts +0 -235
  1596. package/src/utils/background/remote/remoteSession.ts +0 -98
  1597. package/src/utils/backgroundHousekeeping.ts +0 -94
  1598. package/src/utils/bash/ParsedCommand.ts +0 -318
  1599. package/src/utils/bash/ShellSnapshot.ts +0 -582
  1600. package/src/utils/bash/ast.ts +0 -2679
  1601. package/src/utils/bash/bashParser.ts +0 -4436
  1602. package/src/utils/bash/bashPipeCommand.ts +0 -294
  1603. package/src/utils/bash/commands.ts +0 -1339
  1604. package/src/utils/bash/heredoc.ts +0 -733
  1605. package/src/utils/bash/parser.ts +0 -230
  1606. package/src/utils/bash/prefix.ts +0 -204
  1607. package/src/utils/bash/registry.ts +0 -53
  1608. package/src/utils/bash/shellCompletion.ts +0 -259
  1609. package/src/utils/bash/shellPrefix.ts +0 -28
  1610. package/src/utils/bash/shellQuote.ts +0 -304
  1611. package/src/utils/bash/shellQuoting.ts +0 -128
  1612. package/src/utils/bash/specs/alias.ts +0 -14
  1613. package/src/utils/bash/specs/index.ts +0 -18
  1614. package/src/utils/bash/specs/nohup.ts +0 -13
  1615. package/src/utils/bash/specs/pyright.ts +0 -91
  1616. package/src/utils/bash/specs/sleep.ts +0 -13
  1617. package/src/utils/bash/specs/srun.ts +0 -31
  1618. package/src/utils/bash/specs/time.ts +0 -13
  1619. package/src/utils/bash/specs/timeout.ts +0 -20
  1620. package/src/utils/bash/treeSitterAnalysis.ts +0 -506
  1621. package/src/utils/betas.ts +0 -434
  1622. package/src/utils/billing.ts +0 -78
  1623. package/src/utils/binaryCheck.ts +0 -53
  1624. package/src/utils/browser.ts +0 -68
  1625. package/src/utils/bufferedWriter.ts +0 -100
  1626. package/src/utils/bundledMode.ts +0 -22
  1627. package/src/utils/caCerts.ts +0 -115
  1628. package/src/utils/caCertsConfig.ts +0 -88
  1629. package/src/utils/cachePaths.ts +0 -38
  1630. package/src/utils/ccshareResume.ts +0 -2
  1631. package/src/utils/classifierApprovals.ts +0 -88
  1632. package/src/utils/classifierApprovalsHook.ts +0 -17
  1633. package/src/utils/claudeCodeHints.ts +0 -193
  1634. package/src/utils/claudeDesktop.ts +0 -152
  1635. package/src/utils/claudeInChrome/chromeNativeHost.ts +0 -527
  1636. package/src/utils/claudeInChrome/common.ts +0 -540
  1637. package/src/utils/claudeInChrome/mcpServer.ts +0 -293
  1638. package/src/utils/claudeInChrome/prompt.ts +0 -83
  1639. package/src/utils/claudeInChrome/setup.ts +0 -400
  1640. package/src/utils/claudeInChrome/setupPortable.ts +0 -233
  1641. package/src/utils/claudeInChrome/toolRendering.tsx +0 -262
  1642. package/src/utils/claudemd.ts +0 -1479
  1643. package/src/utils/cleanup.ts +0 -602
  1644. package/src/utils/cleanupRegistry.ts +0 -25
  1645. package/src/utils/cliArgs.ts +0 -60
  1646. package/src/utils/cliHighlight.ts +0 -54
  1647. package/src/utils/codeIndexing.ts +0 -206
  1648. package/src/utils/collapseBackgroundBashNotifications.ts +0 -84
  1649. package/src/utils/collapseHookSummaries.ts +0 -59
  1650. package/src/utils/collapseReadSearch.ts +0 -1109
  1651. package/src/utils/collapseTeammateShutdowns.ts +0 -55
  1652. package/src/utils/combinedAbortSignal.ts +0 -47
  1653. package/src/utils/commandLifecycle.ts +0 -21
  1654. package/src/utils/commitAttribution.ts +0 -961
  1655. package/src/utils/completionCache.ts +0 -166
  1656. package/src/utils/computerUse/appNames.ts +0 -196
  1657. package/src/utils/computerUse/cleanup.ts +0 -86
  1658. package/src/utils/computerUse/common.ts +0 -61
  1659. package/src/utils/computerUse/computerUseLock.ts +0 -215
  1660. package/src/utils/computerUse/drainRunLoop.ts +0 -79
  1661. package/src/utils/computerUse/escHotkey.ts +0 -54
  1662. package/src/utils/computerUse/executor.ts +0 -658
  1663. package/src/utils/computerUse/gates.ts +0 -72
  1664. package/src/utils/computerUse/hostAdapter.ts +0 -69
  1665. package/src/utils/computerUse/inputLoader.ts +0 -30
  1666. package/src/utils/computerUse/mcpServer.ts +0 -106
  1667. package/src/utils/computerUse/setup.ts +0 -53
  1668. package/src/utils/computerUse/swiftLoader.ts +0 -23
  1669. package/src/utils/computerUse/toolRendering.tsx +0 -125
  1670. package/src/utils/computerUse/wrapper.tsx +0 -336
  1671. package/src/utils/concurrentSessions.ts +0 -204
  1672. package/src/utils/config.ts +0 -1817
  1673. package/src/utils/configConstants.ts +0 -21
  1674. package/src/utils/contentArray.ts +0 -51
  1675. package/src/utils/context.ts +0 -221
  1676. package/src/utils/contextAnalysis.ts +0 -272
  1677. package/src/utils/contextSuggestions.ts +0 -235
  1678. package/src/utils/controlMessageCompat.ts +0 -32
  1679. package/src/utils/conversationRecovery.ts +0 -597
  1680. package/src/utils/cron.ts +0 -308
  1681. package/src/utils/cronJitterConfig.ts +0 -75
  1682. package/src/utils/cronScheduler.ts +0 -565
  1683. package/src/utils/cronTasks.ts +0 -458
  1684. package/src/utils/cronTasksLock.ts +0 -195
  1685. package/src/utils/crossProjectResume.ts +0 -75
  1686. package/src/utils/crypto.ts +0 -13
  1687. package/src/utils/cwd.ts +0 -32
  1688. package/src/utils/debug.ts +0 -268
  1689. package/src/utils/debugFilter.ts +0 -157
  1690. package/src/utils/deepLink/banner.ts +0 -123
  1691. package/src/utils/deepLink/parseDeepLink.ts +0 -170
  1692. package/src/utils/deepLink/protocolHandler.ts +0 -136
  1693. package/src/utils/deepLink/registerProtocol.ts +0 -348
  1694. package/src/utils/deepLink/terminalLauncher.ts +0 -557
  1695. package/src/utils/deepLink/terminalPreference.ts +0 -54
  1696. package/src/utils/desktopDeepLink.ts +0 -236
  1697. package/src/utils/detectRepository.ts +0 -178
  1698. package/src/utils/diagLogs.ts +0 -94
  1699. package/src/utils/diff.ts +0 -177
  1700. package/src/utils/directMemberMessage.ts +0 -69
  1701. package/src/utils/displayTags.ts +0 -51
  1702. package/src/utils/doctorContextWarnings.ts +0 -265
  1703. package/src/utils/doctorDiagnostic.ts +0 -625
  1704. package/src/utils/dxt/helpers.ts +0 -88
  1705. package/src/utils/dxt/zip.ts +0 -226
  1706. package/src/utils/earlyInput.ts +0 -191
  1707. package/src/utils/editor.ts +0 -183
  1708. package/src/utils/effort.ts +0 -329
  1709. package/src/utils/embeddedTools.ts +0 -29
  1710. package/src/utils/env.ts +0 -347
  1711. package/src/utils/envDynamic.ts +0 -151
  1712. package/src/utils/envUtils.ts +0 -183
  1713. package/src/utils/envValidation.ts +0 -38
  1714. package/src/utils/errorLogSink.ts +0 -235
  1715. package/src/utils/errors.ts +0 -238
  1716. package/src/utils/eventLoopStallDetector.ts +0 -2
  1717. package/src/utils/exampleCommands.ts +0 -184
  1718. package/src/utils/execFileNoThrow.ts +0 -150
  1719. package/src/utils/execFileNoThrowPortable.ts +0 -89
  1720. package/src/utils/execSyncWrapper.ts +0 -38
  1721. package/src/utils/exportRenderer.tsx +0 -98
  1722. package/src/utils/extraUsage.ts +0 -23
  1723. package/src/utils/fastMode.ts +0 -532
  1724. package/src/utils/file.ts +0 -584
  1725. package/src/utils/fileHistory.ts +0 -1115
  1726. package/src/utils/fileOperationAnalytics.ts +0 -71
  1727. package/src/utils/filePersistence/filePersistence.ts +0 -287
  1728. package/src/utils/filePersistence/outputsScanner.ts +0 -126
  1729. package/src/utils/filePersistence/types.ts +0 -33
  1730. package/src/utils/fileRead.ts +0 -102
  1731. package/src/utils/fileReadCache.ts +0 -96
  1732. package/src/utils/fileStateCache.ts +0 -142
  1733. package/src/utils/findExecutable.ts +0 -17
  1734. package/src/utils/fingerprint.ts +0 -76
  1735. package/src/utils/forkedAgent.ts +0 -689
  1736. package/src/utils/format.ts +0 -308
  1737. package/src/utils/formatBriefTimestamp.ts +0 -81
  1738. package/src/utils/fpsTracker.ts +0 -47
  1739. package/src/utils/frontmatterParser.ts +0 -370
  1740. package/src/utils/fsOperations.ts +0 -770
  1741. package/src/utils/fullscreen.ts +0 -202
  1742. package/src/utils/generatedFiles.ts +0 -136
  1743. package/src/utils/generators.ts +0 -88
  1744. package/src/utils/genericProcessUtils.ts +0 -184
  1745. package/src/utils/getWorktreePaths.ts +0 -70
  1746. package/src/utils/getWorktreePathsPortable.ts +0 -27
  1747. package/src/utils/ghPrStatus.ts +0 -106
  1748. package/src/utils/git/gitConfigParser.ts +0 -277
  1749. package/src/utils/git/gitFilesystem.ts +0 -699
  1750. package/src/utils/git/gitignore.ts +0 -99
  1751. package/src/utils/git.ts +0 -926
  1752. package/src/utils/gitDiff.ts +0 -532
  1753. package/src/utils/gitSettings.ts +0 -18
  1754. package/src/utils/github/ghAuthStatus.ts +0 -29
  1755. package/src/utils/githubRepoPathMapping.ts +0 -162
  1756. package/src/utils/glob.ts +0 -130
  1757. package/src/utils/gracefulShutdown.ts +0 -529
  1758. package/src/utils/groupToolUses.ts +0 -182
  1759. package/src/utils/handlePromptSubmit.ts +0 -610
  1760. package/src/utils/hash.ts +0 -46
  1761. package/src/utils/headlessProfiler.ts +0 -178
  1762. package/src/utils/heapDumpService.ts +0 -303
  1763. package/src/utils/heatmap.ts +0 -198
  1764. package/src/utils/highlightMatch.tsx +0 -28
  1765. package/src/utils/hooks/AsyncHookRegistry.ts +0 -309
  1766. package/src/utils/hooks/apiQueryHookHelper.ts +0 -141
  1767. package/src/utils/hooks/execAgentHook.ts +0 -339
  1768. package/src/utils/hooks/execHttpHook.ts +0 -242
  1769. package/src/utils/hooks/execPromptHook.ts +0 -211
  1770. package/src/utils/hooks/fileChangedWatcher.ts +0 -191
  1771. package/src/utils/hooks/hookEvents.ts +0 -192
  1772. package/src/utils/hooks/hookHelpers.ts +0 -83
  1773. package/src/utils/hooks/hooksConfigManager.ts +0 -400
  1774. package/src/utils/hooks/hooksConfigSnapshot.ts +0 -133
  1775. package/src/utils/hooks/hooksSettings.ts +0 -271
  1776. package/src/utils/hooks/postSamplingHooks.ts +0 -70
  1777. package/src/utils/hooks/registerFrontmatterHooks.ts +0 -67
  1778. package/src/utils/hooks/registerSkillHooks.ts +0 -64
  1779. package/src/utils/hooks/sessionHooks.ts +0 -447
  1780. package/src/utils/hooks/skillImprovement.ts +0 -267
  1781. package/src/utils/hooks/ssrfGuard.ts +0 -294
  1782. package/src/utils/hooks.ts +0 -5022
  1783. package/src/utils/horizontalScroll.ts +0 -137
  1784. package/src/utils/http.ts +0 -136
  1785. package/src/utils/hyperlink.ts +0 -39
  1786. package/src/utils/iTermBackup.ts +0 -73
  1787. package/src/utils/ide.ts +0 -1494
  1788. package/src/utils/idePathConversion.ts +0 -90
  1789. package/src/utils/idleTimeout.ts +0 -53
  1790. package/src/utils/imagePaste.ts +0 -416
  1791. package/src/utils/imageResizer.ts +0 -880
  1792. package/src/utils/imageStore.ts +0 -167
  1793. package/src/utils/imageValidation.ts +0 -104
  1794. package/src/utils/immediateCommand.ts +0 -15
  1795. package/src/utils/inProcessTeammateHelpers.ts +0 -102
  1796. package/src/utils/ink.ts +0 -26
  1797. package/src/utils/intl.ts +0 -94
  1798. package/src/utils/jetbrains.ts +0 -191
  1799. package/src/utils/json.ts +0 -277
  1800. package/src/utils/jsonRead.ts +0 -16
  1801. package/src/utils/keyboardShortcuts.ts +0 -14
  1802. package/src/utils/lazySchema.ts +0 -8
  1803. package/src/utils/listSessionsImpl.ts +0 -454
  1804. package/src/utils/localInstaller.ts +0 -162
  1805. package/src/utils/lockfile.ts +0 -43
  1806. package/src/utils/log.ts +0 -362
  1807. package/src/utils/logoV2Utils.ts +0 -350
  1808. package/src/utils/mailbox.ts +0 -73
  1809. package/src/utils/managedEnv.ts +0 -199
  1810. package/src/utils/managedEnvConstants.ts +0 -191
  1811. package/src/utils/markdown.ts +0 -381
  1812. package/src/utils/markdownConfigLoader.ts +0 -600
  1813. package/src/utils/mcp/dateTimeParser.ts +0 -121
  1814. package/src/utils/mcp/elicitationValidation.ts +0 -336
  1815. package/src/utils/mcpInstructionsDelta.ts +0 -130
  1816. package/src/utils/mcpOutputStorage.ts +0 -189
  1817. package/src/utils/mcpValidation.ts +0 -208
  1818. package/src/utils/mcpWebSocketTransport.ts +0 -200
  1819. package/src/utils/memoize.ts +0 -269
  1820. package/src/utils/memory/types.ts +0 -12
  1821. package/src/utils/memory/versions.ts +0 -8
  1822. package/src/utils/memoryFileDetection.ts +0 -289
  1823. package/src/utils/messagePredicates.ts +0 -8
  1824. package/src/utils/messageQueueManager.ts +0 -547
  1825. package/src/utils/messages/mappers.ts +0 -290
  1826. package/src/utils/messages/systemInit.ts +0 -96
  1827. package/src/utils/messages.ts +0 -5512
  1828. package/src/utils/model/agent.ts +0 -157
  1829. package/src/utils/model/aliases.ts +0 -25
  1830. package/src/utils/model/antModels.ts +0 -64
  1831. package/src/utils/model/bedrock.ts +0 -265
  1832. package/src/utils/model/check1mAccess.ts +0 -72
  1833. package/src/utils/model/configs.ts +0 -118
  1834. package/src/utils/model/contextWindowUpgradeCheck.ts +0 -47
  1835. package/src/utils/model/deprecation.ts +0 -101
  1836. package/src/utils/model/model.ts +0 -618
  1837. package/src/utils/model/modelAllowlist.ts +0 -170
  1838. package/src/utils/model/modelCapabilities.ts +0 -118
  1839. package/src/utils/model/modelOptions.ts +0 -540
  1840. package/src/utils/model/modelStrings.ts +0 -166
  1841. package/src/utils/model/modelSupportOverrides.ts +0 -50
  1842. package/src/utils/model/providers.ts +0 -40
  1843. package/src/utils/model/validateModel.ts +0 -159
  1844. package/src/utils/modelCost.ts +0 -231
  1845. package/src/utils/modifiers.ts +0 -41
  1846. package/src/utils/mtls.ts +0 -179
  1847. package/src/utils/nativeInstaller/download.ts +0 -523
  1848. package/src/utils/nativeInstaller/index.ts +0 -18
  1849. package/src/utils/nativeInstaller/installer.ts +0 -1708
  1850. package/src/utils/nativeInstaller/packageManagers.ts +0 -336
  1851. package/src/utils/nativeInstaller/pidLock.ts +0 -433
  1852. package/src/utils/notebook.ts +0 -224
  1853. package/src/utils/objectGroupBy.ts +0 -18
  1854. package/src/utils/pasteStore.ts +0 -104
  1855. package/src/utils/path.ts +0 -155
  1856. package/src/utils/pdf.ts +0 -300
  1857. package/src/utils/pdfUtils.ts +0 -70
  1858. package/src/utils/peerAddress.ts +0 -21
  1859. package/src/utils/permissions/PermissionMode.ts +0 -141
  1860. package/src/utils/permissions/PermissionPromptToolResultSchema.ts +0 -127
  1861. package/src/utils/permissions/PermissionResult.ts +0 -35
  1862. package/src/utils/permissions/PermissionRule.ts +0 -40
  1863. package/src/utils/permissions/PermissionUpdate.ts +0 -389
  1864. package/src/utils/permissions/PermissionUpdateSchema.ts +0 -78
  1865. package/src/utils/permissions/autoModeState.ts +0 -39
  1866. package/src/utils/permissions/bashClassifier.ts +0 -61
  1867. package/src/utils/permissions/bypassPermissionsKillswitch.ts +0 -155
  1868. package/src/utils/permissions/classifierDecision.ts +0 -98
  1869. package/src/utils/permissions/classifierShared.ts +0 -39
  1870. package/src/utils/permissions/dangerousPatterns.ts +0 -80
  1871. package/src/utils/permissions/denialTracking.ts +0 -45
  1872. package/src/utils/permissions/filesystem.ts +0 -1777
  1873. package/src/utils/permissions/getNextPermissionMode.ts +0 -101
  1874. package/src/utils/permissions/pathValidation.ts +0 -485
  1875. package/src/utils/permissions/permissionExplainer.ts +0 -250
  1876. package/src/utils/permissions/permissionRuleParser.ts +0 -198
  1877. package/src/utils/permissions/permissionSetup.ts +0 -1532
  1878. package/src/utils/permissions/permissions.ts +0 -1486
  1879. package/src/utils/permissions/permissionsLoader.ts +0 -296
  1880. package/src/utils/permissions/shadowedRuleDetection.ts +0 -234
  1881. package/src/utils/permissions/shellRuleMatching.ts +0 -228
  1882. package/src/utils/permissions/yolo-classifier-prompts/auto_mode_system_prompt.txt +0 -1
  1883. package/src/utils/permissions/yolo-classifier-prompts/permissions_anthropic.txt +0 -1
  1884. package/src/utils/permissions/yolo-classifier-prompts/permissions_external.txt +0 -1
  1885. package/src/utils/permissions/yoloClassifier.ts +0 -1495
  1886. package/src/utils/planModeV2.ts +0 -95
  1887. package/src/utils/plans.ts +0 -397
  1888. package/src/utils/platform.ts +0 -150
  1889. package/src/utils/plugins/addDirPluginSettings.ts +0 -71
  1890. package/src/utils/plugins/cacheUtils.ts +0 -196
  1891. package/src/utils/plugins/dependencyResolver.ts +0 -305
  1892. package/src/utils/plugins/fetchTelemetry.ts +0 -135
  1893. package/src/utils/plugins/gitAvailability.ts +0 -69
  1894. package/src/utils/plugins/headlessPluginInstall.ts +0 -174
  1895. package/src/utils/plugins/hintRecommendation.ts +0 -164
  1896. package/src/utils/plugins/installCounts.ts +0 -292
  1897. package/src/utils/plugins/installedPluginsManager.ts +0 -1268
  1898. package/src/utils/plugins/loadPluginAgents.ts +0 -348
  1899. package/src/utils/plugins/loadPluginCommands.ts +0 -946
  1900. package/src/utils/plugins/loadPluginHooks.ts +0 -287
  1901. package/src/utils/plugins/loadPluginOutputStyles.ts +0 -178
  1902. package/src/utils/plugins/lspPluginIntegration.ts +0 -387
  1903. package/src/utils/plugins/lspRecommendation.ts +0 -374
  1904. package/src/utils/plugins/managedPlugins.ts +0 -27
  1905. package/src/utils/plugins/marketplaceHelpers.ts +0 -592
  1906. package/src/utils/plugins/marketplaceManager.ts +0 -2643
  1907. package/src/utils/plugins/mcpPluginIntegration.ts +0 -634
  1908. package/src/utils/plugins/mcpbHandler.ts +0 -968
  1909. package/src/utils/plugins/officialMarketplace.ts +0 -25
  1910. package/src/utils/plugins/officialMarketplaceGcs.ts +0 -216
  1911. package/src/utils/plugins/officialMarketplaceStartupCheck.ts +0 -439
  1912. package/src/utils/plugins/orphanedPluginFilter.ts +0 -114
  1913. package/src/utils/plugins/parseMarketplaceInput.ts +0 -162
  1914. package/src/utils/plugins/performStartupChecks.tsx +0 -70
  1915. package/src/utils/plugins/pluginAutoupdate.ts +0 -284
  1916. package/src/utils/plugins/pluginBlocklist.ts +0 -127
  1917. package/src/utils/plugins/pluginDirectories.ts +0 -178
  1918. package/src/utils/plugins/pluginFlagging.ts +0 -208
  1919. package/src/utils/plugins/pluginIdentifier.ts +0 -123
  1920. package/src/utils/plugins/pluginInstallationHelpers.ts +0 -595
  1921. package/src/utils/plugins/pluginLoader.ts +0 -3302
  1922. package/src/utils/plugins/pluginOptionsStorage.ts +0 -400
  1923. package/src/utils/plugins/pluginPolicy.ts +0 -20
  1924. package/src/utils/plugins/pluginStartupCheck.ts +0 -341
  1925. package/src/utils/plugins/pluginVersioning.ts +0 -157
  1926. package/src/utils/plugins/reconciler.ts +0 -265
  1927. package/src/utils/plugins/refresh.ts +0 -215
  1928. package/src/utils/plugins/schemas.ts +0 -1681
  1929. package/src/utils/plugins/validatePlugin.ts +0 -903
  1930. package/src/utils/plugins/walkPluginMarkdown.ts +0 -69
  1931. package/src/utils/plugins/zipCache.ts +0 -406
  1932. package/src/utils/plugins/zipCacheAdapters.ts +0 -164
  1933. package/src/utils/postCommitAttribution.ts +0 -2
  1934. package/src/utils/powershell/dangerousCmdlets.ts +0 -185
  1935. package/src/utils/powershell/parser.ts +0 -1804
  1936. package/src/utils/powershell/staticPrefix.ts +0 -316
  1937. package/src/utils/preflightChecks.tsx +0 -151
  1938. package/src/utils/privacyLevel.ts +0 -55
  1939. package/src/utils/process.ts +0 -68
  1940. package/src/utils/processUserInput/processBashCommand.tsx +0 -140
  1941. package/src/utils/processUserInput/processSlashCommand.tsx +0 -922
  1942. package/src/utils/processUserInput/processTextPrompt.ts +0 -100
  1943. package/src/utils/processUserInput/processUserInput.ts +0 -605
  1944. package/src/utils/profilerBase.ts +0 -46
  1945. package/src/utils/promptCategory.ts +0 -49
  1946. package/src/utils/promptEditor.ts +0 -188
  1947. package/src/utils/promptShellExecution.ts +0 -183
  1948. package/src/utils/protectedNamespace.ts +0 -2
  1949. package/src/utils/proxy.ts +0 -426
  1950. package/src/utils/queryContext.ts +0 -179
  1951. package/src/utils/queryHelpers.ts +0 -552
  1952. package/src/utils/queryProfiler.ts +0 -301
  1953. package/src/utils/queueProcessor.ts +0 -95
  1954. package/src/utils/readEditContext.ts +0 -227
  1955. package/src/utils/readFileInRange.ts +0 -383
  1956. package/src/utils/releaseNotes.ts +0 -360
  1957. package/src/utils/renderOptions.ts +0 -77
  1958. package/src/utils/ripgrep.ts +0 -679
  1959. package/src/utils/sandbox/sandbox-adapter.ts +0 -985
  1960. package/src/utils/sandbox/sandbox-ui-utils.ts +0 -12
  1961. package/src/utils/sanitization.ts +0 -91
  1962. package/src/utils/screenshotClipboard.ts +0 -121
  1963. package/src/utils/sdkEventQueue.ts +0 -134
  1964. package/src/utils/sdkHeapDumpMonitor.ts +0 -2
  1965. package/src/utils/secureStorage/fallbackStorage.ts +0 -70
  1966. package/src/utils/secureStorage/index.ts +0 -17
  1967. package/src/utils/secureStorage/keychainPrefetch.ts +0 -116
  1968. package/src/utils/secureStorage/macOsKeychainHelpers.ts +0 -111
  1969. package/src/utils/secureStorage/macOsKeychainStorage.ts +0 -231
  1970. package/src/utils/secureStorage/plainTextStorage.ts +0 -84
  1971. package/src/utils/secureStorage/types.ts +0 -2
  1972. package/src/utils/semanticBoolean.ts +0 -29
  1973. package/src/utils/semanticNumber.ts +0 -36
  1974. package/src/utils/semver.ts +0 -59
  1975. package/src/utils/sequential.ts +0 -56
  1976. package/src/utils/sessionActivity.ts +0 -133
  1977. package/src/utils/sessionDataUploader.ts +0 -2
  1978. package/src/utils/sessionEnvVars.ts +0 -22
  1979. package/src/utils/sessionEnvironment.ts +0 -166
  1980. package/src/utils/sessionFileAccessHooks.ts +0 -250
  1981. package/src/utils/sessionIngressAuth.ts +0 -140
  1982. package/src/utils/sessionRestore.ts +0 -551
  1983. package/src/utils/sessionStart.ts +0 -232
  1984. package/src/utils/sessionState.ts +0 -150
  1985. package/src/utils/sessionStorage.ts +0 -5105
  1986. package/src/utils/sessionStoragePortable.ts +0 -793
  1987. package/src/utils/sessionTitle.ts +0 -129
  1988. package/src/utils/sessionUrl.ts +0 -64
  1989. package/src/utils/set.ts +0 -53
  1990. package/src/utils/settings/allErrors.ts +0 -32
  1991. package/src/utils/settings/applySettingsChange.ts +0 -92
  1992. package/src/utils/settings/changeDetector.ts +0 -488
  1993. package/src/utils/settings/constants.ts +0 -202
  1994. package/src/utils/settings/internalWrites.ts +0 -37
  1995. package/src/utils/settings/managedPath.ts +0 -34
  1996. package/src/utils/settings/mdm/constants.ts +0 -81
  1997. package/src/utils/settings/mdm/rawRead.ts +0 -130
  1998. package/src/utils/settings/mdm/settings.ts +0 -316
  1999. package/src/utils/settings/permissionValidation.ts +0 -262
  2000. package/src/utils/settings/pluginOnlyPolicy.ts +0 -60
  2001. package/src/utils/settings/schemaOutput.ts +0 -8
  2002. package/src/utils/settings/settings.ts +0 -1015
  2003. package/src/utils/settings/settingsCache.ts +0 -80
  2004. package/src/utils/settings/toolValidationConfig.ts +0 -103
  2005. package/src/utils/settings/types.ts +0 -1148
  2006. package/src/utils/settings/validateEditTool.ts +0 -45
  2007. package/src/utils/settings/validation.ts +0 -265
  2008. package/src/utils/settings/validationTips.ts +0 -164
  2009. package/src/utils/shell/bashProvider.ts +0 -255
  2010. package/src/utils/shell/outputLimits.ts +0 -14
  2011. package/src/utils/shell/powershellDetection.ts +0 -107
  2012. package/src/utils/shell/powershellProvider.ts +0 -123
  2013. package/src/utils/shell/prefix.ts +0 -367
  2014. package/src/utils/shell/readOnlyCommandValidation.ts +0 -1893
  2015. package/src/utils/shell/resolveDefaultShell.ts +0 -14
  2016. package/src/utils/shell/shellProvider.ts +0 -33
  2017. package/src/utils/shell/shellToolUtils.ts +0 -22
  2018. package/src/utils/shell/specPrefix.ts +0 -241
  2019. package/src/utils/shellConfig.ts +0 -167
  2020. package/src/utils/sideQuery.ts +0 -222
  2021. package/src/utils/sideQuestion.ts +0 -155
  2022. package/src/utils/signal.ts +0 -43
  2023. package/src/utils/sinks.ts +0 -16
  2024. package/src/utils/skills/skillChangeDetector.ts +0 -311
  2025. package/src/utils/slashCommandParsing.ts +0 -60
  2026. package/src/utils/sleep.ts +0 -84
  2027. package/src/utils/sliceAnsi.ts +0 -91
  2028. package/src/utils/slowOperations.ts +0 -286
  2029. package/src/utils/standaloneAgent.ts +0 -23
  2030. package/src/utils/startupProfiler.ts +0 -194
  2031. package/src/utils/staticRender.tsx +0 -116
  2032. package/src/utils/stats.ts +0 -1061
  2033. package/src/utils/statsCache.ts +0 -434
  2034. package/src/utils/status.tsx +0 -362
  2035. package/src/utils/statusNoticeDefinitions.tsx +0 -198
  2036. package/src/utils/statusNoticeHelpers.ts +0 -20
  2037. package/src/utils/stream.ts +0 -76
  2038. package/src/utils/streamJsonStdoutGuard.ts +0 -123
  2039. package/src/utils/streamlinedTransform.ts +0 -201
  2040. package/src/utils/stringUtils.ts +0 -235
  2041. package/src/utils/subprocessEnv.ts +0 -99
  2042. package/src/utils/suggestions/commandSuggestions.ts +0 -567
  2043. package/src/utils/suggestions/directoryCompletion.ts +0 -263
  2044. package/src/utils/suggestions/shellHistoryCompletion.ts +0 -119
  2045. package/src/utils/suggestions/skillUsageTracking.ts +0 -55
  2046. package/src/utils/suggestions/slackChannelSuggestions.ts +0 -209
  2047. package/src/utils/swarm/It2SetupPrompt.tsx +0 -380
  2048. package/src/utils/swarm/backends/ITermBackend.ts +0 -370
  2049. package/src/utils/swarm/backends/InProcessBackend.ts +0 -339
  2050. package/src/utils/swarm/backends/PaneBackendExecutor.ts +0 -354
  2051. package/src/utils/swarm/backends/TmuxBackend.ts +0 -764
  2052. package/src/utils/swarm/backends/detection.ts +0 -128
  2053. package/src/utils/swarm/backends/it2Setup.ts +0 -245
  2054. package/src/utils/swarm/backends/registry.ts +0 -464
  2055. package/src/utils/swarm/backends/teammateModeSnapshot.ts +0 -87
  2056. package/src/utils/swarm/backends/types.ts +0 -311
  2057. package/src/utils/swarm/constants.ts +0 -33
  2058. package/src/utils/swarm/inProcessRunner.ts +0 -1552
  2059. package/src/utils/swarm/leaderPermissionBridge.ts +0 -54
  2060. package/src/utils/swarm/permissionSync.ts +0 -928
  2061. package/src/utils/swarm/reconnection.ts +0 -119
  2062. package/src/utils/swarm/spawnInProcess.ts +0 -328
  2063. package/src/utils/swarm/spawnUtils.ts +0 -146
  2064. package/src/utils/swarm/teamHelpers.ts +0 -683
  2065. package/src/utils/swarm/teammateInit.ts +0 -129
  2066. package/src/utils/swarm/teammateLayoutManager.ts +0 -107
  2067. package/src/utils/swarm/teammateModel.ts +0 -10
  2068. package/src/utils/swarm/teammatePromptAddendum.ts +0 -18
  2069. package/src/utils/systemDirectories.ts +0 -74
  2070. package/src/utils/systemPrompt.ts +0 -123
  2071. package/src/utils/systemPromptType.ts +0 -14
  2072. package/src/utils/systemTheme.ts +0 -119
  2073. package/src/utils/systemThemeWatcher.ts +0 -2
  2074. package/src/utils/taggedId.ts +0 -54
  2075. package/src/utils/task/TaskOutput.ts +0 -390
  2076. package/src/utils/task/diskOutput.ts +0 -451
  2077. package/src/utils/task/framework.ts +0 -308
  2078. package/src/utils/task/outputFormatting.ts +0 -38
  2079. package/src/utils/task/sdkProgress.ts +0 -36
  2080. package/src/utils/taskSummary.ts +0 -2
  2081. package/src/utils/tasks.ts +0 -862
  2082. package/src/utils/teamDiscovery.ts +0 -81
  2083. package/src/utils/teamMemoryOps.ts +0 -88
  2084. package/src/utils/teammate.ts +0 -292
  2085. package/src/utils/teammateContext.ts +0 -96
  2086. package/src/utils/teammateMailbox.ts +0 -1183
  2087. package/src/utils/telemetry/betaSessionTracing.ts +0 -491
  2088. package/src/utils/telemetry/bigqueryExporter.ts +0 -252
  2089. package/src/utils/telemetry/events.ts +0 -75
  2090. package/src/utils/telemetry/instrumentation.ts +0 -825
  2091. package/src/utils/telemetry/logger.ts +0 -26
  2092. package/src/utils/telemetry/perfettoTracing.ts +0 -1120
  2093. package/src/utils/telemetry/pluginTelemetry.ts +0 -289
  2094. package/src/utils/telemetry/sessionTracing.ts +0 -927
  2095. package/src/utils/telemetry/skillLoadedEvent.ts +0 -39
  2096. package/src/utils/telemetryAttributes.ts +0 -71
  2097. package/src/utils/teleport/api.ts +0 -466
  2098. package/src/utils/teleport/environmentSelection.ts +0 -77
  2099. package/src/utils/teleport/environments.ts +0 -120
  2100. package/src/utils/teleport/gitBundle.ts +0 -292
  2101. package/src/utils/teleport.tsx +0 -1226
  2102. package/src/utils/tempfile.ts +0 -31
  2103. package/src/utils/terminal.ts +0 -131
  2104. package/src/utils/terminalPanel.ts +0 -191
  2105. package/src/utils/textHighlighting.ts +0 -166
  2106. package/src/utils/theme.ts +0 -639
  2107. package/src/utils/thinking.ts +0 -162
  2108. package/src/utils/timeouts.ts +0 -39
  2109. package/src/utils/tmuxSocket.ts +0 -427
  2110. package/src/utils/todo/types.ts +0 -18
  2111. package/src/utils/tokenBudget.ts +0 -73
  2112. package/src/utils/tokens.ts +0 -261
  2113. package/src/utils/toolErrors.ts +0 -132
  2114. package/src/utils/toolPool.ts +0 -79
  2115. package/src/utils/toolResultStorage.ts +0 -1040
  2116. package/src/utils/toolSchemaCache.ts +0 -26
  2117. package/src/utils/toolSearch.ts +0 -756
  2118. package/src/utils/transcriptSearch.ts +0 -202
  2119. package/src/utils/treeify.ts +0 -170
  2120. package/src/utils/truncate.ts +0 -179
  2121. package/src/utils/udsClient.ts +0 -2
  2122. package/src/utils/udsMessaging.ts +0 -2
  2123. package/src/utils/ultraplan/ccrSession.ts +0 -349
  2124. package/src/utils/ultraplan/keyword.ts +0 -127
  2125. package/src/utils/ultraplan/prompt.txt +0 -1
  2126. package/src/utils/unaryLogging.ts +0 -39
  2127. package/src/utils/undercover.ts +0 -89
  2128. package/src/utils/user.ts +0 -194
  2129. package/src/utils/userAgent.ts +0 -10
  2130. package/src/utils/userPromptKeywords.ts +0 -27
  2131. package/src/utils/uuid.ts +0 -27
  2132. package/src/utils/warningHandler.ts +0 -121
  2133. package/src/utils/which.ts +0 -82
  2134. package/src/utils/windowsPaths.ts +0 -173
  2135. package/src/utils/withResolvers.ts +0 -13
  2136. package/src/utils/words.ts +0 -800
  2137. package/src/utils/workloadContext.ts +0 -57
  2138. package/src/utils/worktree.ts +0 -1519
  2139. package/src/utils/worktreeModeEnabled.ts +0 -11
  2140. package/src/utils/xdg.ts +0 -65
  2141. package/src/utils/xml.ts +0 -16
  2142. package/src/utils/yaml.ts +0 -15
  2143. package/src/utils/zodToJsonSchema.ts +0 -23
  2144. package/src/vim/motions.ts +0 -82
  2145. package/src/vim/operators.ts +0 -556
  2146. package/src/vim/textObjects.ts +0 -186
  2147. package/src/vim/transitions.ts +0 -490
  2148. package/src/vim/types.ts +0 -199
  2149. package/src/voice/voiceModeEnabled.ts +0 -54
  2150. package/stubs/@ant/claude-for-chrome-mcp/index.js +0 -1
  2151. package/stubs/@ant/claude-for-chrome-mcp/index.ts +0 -4
  2152. package/stubs/@ant/claude-for-chrome-mcp/package.json +0 -6
  2153. package/stubs/@ant/computer-use-input/index.js +0 -2
  2154. package/stubs/@ant/computer-use-input/index.ts +0 -3
  2155. package/stubs/@ant/computer-use-input/package.json +0 -6
  2156. package/stubs/@ant/computer-use-mcp/index.js +0 -1
  2157. package/stubs/@ant/computer-use-mcp/index.ts +0 -1
  2158. package/stubs/@ant/computer-use-mcp/package.json +0 -11
  2159. package/stubs/@ant/computer-use-mcp/sentinelApps.js +0 -3
  2160. package/stubs/@ant/computer-use-mcp/sentinelApps.ts +0 -3
  2161. package/stubs/@ant/computer-use-mcp/types.js +0 -2
  2162. package/stubs/@ant/computer-use-mcp/types.ts +0 -6
  2163. package/stubs/@ant/computer-use-swift/index.js +0 -2
  2164. package/stubs/@ant/computer-use-swift/index.ts +0 -2
  2165. package/stubs/@ant/computer-use-swift/package.json +0 -6
  2166. package/stubs/@anthropic-ai/claude-agent-sdk/index.js +0 -2
  2167. package/stubs/@anthropic-ai/claude-agent-sdk/index.ts +0 -2
  2168. package/stubs/@anthropic-ai/claude-agent-sdk/package.json +0 -6
  2169. package/stubs/@anthropic-ai/mcpb/index.js +0 -2
  2170. package/stubs/@anthropic-ai/mcpb/index.ts +0 -3
  2171. package/stubs/@anthropic-ai/mcpb/package.json +0 -6
  2172. package/stubs/@anthropic-ai/sandbox-runtime/index.js +0 -4
  2173. package/stubs/@anthropic-ai/sandbox-runtime/index.ts +0 -49
  2174. package/stubs/@anthropic-ai/sandbox-runtime/package.json +0 -6
  2175. package/stubs/globals.ts +0 -11
  2176. package/stubs/macro.d.ts +0 -9
  2177. package/tsconfig.json +0 -28
@@ -1,5022 +0,0 @@
1
- // biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered
2
- /**
3
- * Hooks are user-defined shell commands that can be executed at various points
4
- * in Claude Code's lifecycle.
5
- */
6
- import { basename } from 'path'
7
- import { spawn, type ChildProcessWithoutNullStreams } from 'child_process'
8
- import { pathExists } from './file.js'
9
- import { wrapSpawn } from './ShellCommand.js'
10
- import { TaskOutput } from './task/TaskOutput.js'
11
- import { getCwd } from './cwd.js'
12
- import { randomUUID } from 'crypto'
13
- import { formatShellPrefixCommand } from './bash/shellPrefix.js'
14
- import {
15
- getHookEnvFilePath,
16
- invalidateSessionEnvCache,
17
- } from './sessionEnvironment.js'
18
- import { subprocessEnv } from './subprocessEnv.js'
19
- import { getPlatform } from './platform.js'
20
- import { findGitBashPath, windowsPathToPosixPath } from './windowsPaths.js'
21
- import { getCachedPowerShellPath } from './shell/powershellDetection.js'
22
- import { DEFAULT_HOOK_SHELL } from './shell/shellProvider.js'
23
- import { buildPowerShellArgs } from './shell/powershellProvider.js'
24
- import {
25
- loadPluginOptions,
26
- substituteUserConfigVariables,
27
- } from './plugins/pluginOptionsStorage.js'
28
- import { getPluginDataDir } from './plugins/pluginDirectories.js'
29
- import {
30
- getSessionId,
31
- getProjectRoot,
32
- getIsNonInteractiveSession,
33
- getRegisteredHooks,
34
- getStatsStore,
35
- addToTurnHookDuration,
36
- getOriginalCwd,
37
- getMainThreadAgentType,
38
- } from '../bootstrap/state.js'
39
- import { checkHasTrustDialogAccepted } from './config.js'
40
- import {
41
- getHooksConfigFromSnapshot,
42
- shouldAllowManagedHooksOnly,
43
- shouldDisableAllHooksIncludingManaged,
44
- } from './hooks/hooksConfigSnapshot.js'
45
- import {
46
- getTranscriptPathForSession,
47
- getAgentTranscriptPath,
48
- } from './sessionStorage.js'
49
- import type { AgentId } from '../types/ids.js'
50
- import {
51
- getSettings_DEPRECATED,
52
- getSettingsForSource,
53
- } from './settings/settings.js'
54
- import {
55
- logEvent,
56
- type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
57
- } from 'src/services/analytics/index.js'
58
- import { logOTelEvent } from './telemetry/events.js'
59
- import { ALLOWED_OFFICIAL_MARKETPLACE_NAMES } from './plugins/schemas.js'
60
- import {
61
- startHookSpan,
62
- endHookSpan,
63
- isBetaTracingEnabled,
64
- } from './telemetry/sessionTracing.js'
65
- import {
66
- hookJSONOutputSchema,
67
- promptRequestSchema,
68
- type HookCallback,
69
- type HookCallbackMatcher,
70
- type PromptRequest,
71
- type PromptResponse,
72
- isAsyncHookJSONOutput,
73
- isSyncHookJSONOutput,
74
- type PermissionRequestResult,
75
- } from '../types/hooks.js'
76
- import type {
77
- HookEvent,
78
- HookInput,
79
- HookJSONOutput,
80
- NotificationHookInput,
81
- PostToolUseHookInput,
82
- PostToolUseFailureHookInput,
83
- PermissionDeniedHookInput,
84
- PreCompactHookInput,
85
- PostCompactHookInput,
86
- PreToolUseHookInput,
87
- SessionStartHookInput,
88
- SessionEndHookInput,
89
- SetupHookInput,
90
- StopHookInput,
91
- StopFailureHookInput,
92
- SubagentStartHookInput,
93
- SubagentStopHookInput,
94
- TeammateIdleHookInput,
95
- TaskCreatedHookInput,
96
- TaskCompletedHookInput,
97
- ConfigChangeHookInput,
98
- CwdChangedHookInput,
99
- FileChangedHookInput,
100
- InstructionsLoadedHookInput,
101
- UserPromptSubmitHookInput,
102
- PermissionRequestHookInput,
103
- ElicitationHookInput,
104
- ElicitationResultHookInput,
105
- PermissionUpdate,
106
- ExitReason,
107
- SyncHookJSONOutput,
108
- AsyncHookJSONOutput,
109
- } from 'src/entrypoints/agentSdkTypes.js'
110
- import type { StatusLineCommandInput } from '../types/statusLine.js'
111
- import type { ElicitResult } from '@modelcontextprotocol/sdk/types.js'
112
- import type { FileSuggestionCommandInput } from '../types/fileSuggestion.js'
113
- import type { HookResultMessage } from 'src/types/message.js'
114
- import chalk from 'chalk'
115
- import type {
116
- HookMatcher,
117
- HookCommand,
118
- PluginHookMatcher,
119
- SkillHookMatcher,
120
- } from './settings/types.js'
121
- import { getHookDisplayText } from './hooks/hooksSettings.js'
122
- import { logForDebugging } from './debug.js'
123
- import { logForDiagnosticsNoPII } from './diagLogs.js'
124
- import { firstLineOf } from './stringUtils.js'
125
- import {
126
- normalizeLegacyToolName,
127
- getLegacyToolNames,
128
- permissionRuleValueFromString,
129
- } from './permissions/permissionRuleParser.js'
130
- import { logError } from './log.js'
131
- import { createCombinedAbortSignal } from './combinedAbortSignal.js'
132
- import type { PermissionResult } from './permissions/PermissionResult.js'
133
- import { registerPendingAsyncHook } from './hooks/AsyncHookRegistry.js'
134
- import { enqueuePendingNotification } from './messageQueueManager.js'
135
- import {
136
- extractTextContent,
137
- getLastAssistantMessage,
138
- wrapInSystemReminder,
139
- } from './messages.js'
140
- import {
141
- emitHookStarted,
142
- emitHookResponse,
143
- startHookProgressInterval,
144
- } from './hooks/hookEvents.js'
145
- import { createAttachmentMessage } from './attachments.js'
146
- import { all } from './generators.js'
147
- import { findToolByName, type Tools, type ToolUseContext } from '../Tool.js'
148
- import { execPromptHook } from './hooks/execPromptHook.js'
149
- import type { Message, AssistantMessage } from '../types/message.js'
150
- import { execAgentHook } from './hooks/execAgentHook.js'
151
- import { execHttpHook } from './hooks/execHttpHook.js'
152
- import type { ShellCommand } from './ShellCommand.js'
153
- import {
154
- getSessionHooks,
155
- getSessionFunctionHooks,
156
- getSessionHookCallback,
157
- clearSessionHooks,
158
- type SessionDerivedHookMatcher,
159
- type FunctionHook,
160
- } from './hooks/sessionHooks.js'
161
- import type { AppState } from '../state/AppState.js'
162
- import { jsonStringify, jsonParse } from './slowOperations.js'
163
- import { isEnvTruthy } from './envUtils.js'
164
- import { errorMessage, getErrnoCode } from './errors.js'
165
-
166
- const TOOL_HOOK_EXECUTION_TIMEOUT_MS = 10 * 60 * 1000
167
-
168
- /**
169
- * SessionEnd hooks run during shutdown/clear and need a much tighter bound
170
- * than TOOL_HOOK_EXECUTION_TIMEOUT_MS. This value is used by callers as both
171
- * the per-hook default timeout AND the overall AbortSignal cap (hooks run in
172
- * parallel, so one value suffices). Overridable via env var for users whose
173
- * teardown scripts need more time.
174
- */
175
- const SESSION_END_HOOK_TIMEOUT_MS_DEFAULT = 1500
176
- export function getSessionEndHookTimeoutMs(): number {
177
- const raw = process.env.CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS
178
- const parsed = raw ? parseInt(raw, 10) : NaN
179
- return Number.isFinite(parsed) && parsed > 0
180
- ? parsed
181
- : SESSION_END_HOOK_TIMEOUT_MS_DEFAULT
182
- }
183
-
184
- function executeInBackground({
185
- processId,
186
- hookId,
187
- shellCommand,
188
- asyncResponse,
189
- hookEvent,
190
- hookName,
191
- command,
192
- asyncRewake,
193
- pluginId,
194
- }: {
195
- processId: string
196
- hookId: string
197
- shellCommand: ShellCommand
198
- asyncResponse: AsyncHookJSONOutput
199
- hookEvent: HookEvent | 'StatusLine' | 'FileSuggestion'
200
- hookName: string
201
- command: string
202
- asyncRewake?: boolean
203
- pluginId?: string
204
- }): boolean {
205
- if (asyncRewake) {
206
- // asyncRewake hooks bypass the registry entirely. On completion, if exit
207
- // code 2 (blocking error), enqueue as a task-notification so it wakes the
208
- // model via useQueueProcessor (idle) or gets injected mid-query via
209
- // queued_command attachments (busy).
210
- //
211
- // NOTE: We deliberately do NOT call shellCommand.background() here, because
212
- // it calls taskOutput.spillToDisk() which breaks in-memory stdout/stderr
213
- // capture (getStderr() returns '' in disk mode). The StreamWrappers stay
214
- // attached and pipe data into the in-memory TaskOutput buffers. The abort
215
- // handler already no-ops on 'interrupt' reason (user submitted a new
216
- // message), so the hook survives new prompts. A hard cancel (Escape) WILL
217
- // kill the hook via the abort handler, which is the desired behavior.
218
- void shellCommand.result.then(async result => {
219
- // result resolves on 'exit', but stdio 'data' events may still be
220
- // pending. Yield to I/O so the StreamWrapper data handlers drain into
221
- // TaskOutput before we read it.
222
- await new Promise(resolve => setImmediate(resolve))
223
- const stdout = await shellCommand.taskOutput.getStdout()
224
- const stderr = shellCommand.taskOutput.getStderr()
225
- shellCommand.cleanup()
226
- emitHookResponse({
227
- hookId,
228
- hookName,
229
- hookEvent,
230
- output: stdout + stderr,
231
- stdout,
232
- stderr,
233
- exitCode: result.code,
234
- outcome: result.code === 0 ? 'success' : 'error',
235
- })
236
- if (result.code === 2) {
237
- enqueuePendingNotification({
238
- value: wrapInSystemReminder(
239
- `Stop hook blocking error from command "${hookName}": ${stderr || stdout}`,
240
- ),
241
- mode: 'task-notification',
242
- })
243
- }
244
- })
245
- return true
246
- }
247
-
248
- // TaskOutput on the ShellCommand accumulates data — no stream listeners needed
249
- if (!shellCommand.background(processId)) {
250
- return false
251
- }
252
-
253
- registerPendingAsyncHook({
254
- processId,
255
- hookId,
256
- asyncResponse,
257
- hookEvent,
258
- hookName,
259
- command,
260
- shellCommand,
261
- pluginId,
262
- })
263
-
264
- return true
265
- }
266
-
267
- /**
268
- * Checks if a hook should be skipped due to lack of workspace trust.
269
- *
270
- * ALL hooks require workspace trust because they execute arbitrary commands from
271
- * .claude/settings.json. This is a defense-in-depth security measure.
272
- *
273
- * Context: Hooks are captured via captureHooksConfigSnapshot() before the trust
274
- * dialog is shown. While most hooks won't execute until after trust is established
275
- * through normal program flow, enforcing trust for ALL hooks prevents:
276
- * - Future bugs where a hook might accidentally execute before trust
277
- * - Any codepath that might trigger hooks before trust dialog
278
- * - Security issues from hook execution in untrusted workspaces
279
- *
280
- * Historical vulnerabilities that prompted this check:
281
- * - SessionEnd hooks executing when user declines trust dialog
282
- * - SubagentStop hooks executing when subagent completes before trust
283
- *
284
- * @returns true if hook should be skipped, false if it should execute
285
- */
286
- export function shouldSkipHookDueToTrust(): boolean {
287
- // In non-interactive mode (SDK), trust is implicit - always execute
288
- const isInteractive = !getIsNonInteractiveSession()
289
- if (!isInteractive) {
290
- return false
291
- }
292
-
293
- // In interactive mode, ALL hooks require trust
294
- const hasTrust = checkHasTrustDialogAccepted()
295
- return !hasTrust
296
- }
297
-
298
- /**
299
- * Creates the base hook input that's common to all hook types
300
- */
301
- export function createBaseHookInput(
302
- permissionMode?: string,
303
- sessionId?: string,
304
- // Typed narrowly (not ToolUseContext) so callers can pass toolUseContext
305
- // directly via structural typing without this function depending on Tool.ts.
306
- agentInfo?: { agentId?: string; agentType?: string },
307
- ): {
308
- session_id: string
309
- transcript_path: string
310
- cwd: string
311
- permission_mode?: string
312
- agent_id?: string
313
- agent_type?: string
314
- } {
315
- const resolvedSessionId = sessionId ?? getSessionId()
316
- // agent_type: subagent's type (from toolUseContext) takes precedence over
317
- // the session's --agent flag. Hooks use agent_id presence to distinguish
318
- // subagent calls from main-thread calls in a --agent session.
319
- const resolvedAgentType = agentInfo?.agentType ?? getMainThreadAgentType()
320
- return {
321
- session_id: resolvedSessionId,
322
- transcript_path: getTranscriptPathForSession(resolvedSessionId),
323
- cwd: getCwd(),
324
- permission_mode: permissionMode,
325
- agent_id: agentInfo?.agentId,
326
- agent_type: resolvedAgentType,
327
- }
328
- }
329
-
330
- export interface HookBlockingError {
331
- blockingError: string
332
- command: string
333
- }
334
-
335
- /** Re-export ElicitResult from MCP SDK as ElicitationResponse for backward compat. */
336
- export type ElicitationResponse = ElicitResult
337
-
338
- export interface HookResult {
339
- message?: HookResultMessage
340
- systemMessage?: string
341
- blockingError?: HookBlockingError
342
- outcome: 'success' | 'blocking' | 'non_blocking_error' | 'cancelled'
343
- preventContinuation?: boolean
344
- stopReason?: string
345
- permissionBehavior?: 'ask' | 'deny' | 'allow' | 'passthrough'
346
- hookPermissionDecisionReason?: string
347
- additionalContext?: string
348
- initialUserMessage?: string
349
- updatedInput?: Record<string, unknown>
350
- updatedMCPToolOutput?: unknown
351
- permissionRequestResult?: PermissionRequestResult
352
- elicitationResponse?: ElicitationResponse
353
- watchPaths?: string[]
354
- elicitationResultResponse?: ElicitationResponse
355
- retry?: boolean
356
- hook: HookCommand | HookCallback | FunctionHook
357
- }
358
-
359
- export type AggregatedHookResult = {
360
- message?: HookResultMessage
361
- blockingError?: HookBlockingError
362
- preventContinuation?: boolean
363
- stopReason?: string
364
- hookPermissionDecisionReason?: string
365
- hookSource?: string
366
- permissionBehavior?: PermissionResult['behavior']
367
- additionalContexts?: string[]
368
- initialUserMessage?: string
369
- updatedInput?: Record<string, unknown>
370
- updatedMCPToolOutput?: unknown
371
- permissionRequestResult?: PermissionRequestResult
372
- watchPaths?: string[]
373
- elicitationResponse?: ElicitationResponse
374
- elicitationResultResponse?: ElicitationResponse
375
- retry?: boolean
376
- }
377
-
378
- /**
379
- * Parse and validate a JSON string against the hook output Zod schema.
380
- * Returns the validated output or formatted validation errors.
381
- */
382
- function validateHookJson(
383
- jsonString: string,
384
- ): { json: HookJSONOutput } | { validationError: string } {
385
- const parsed = jsonParse(jsonString)
386
- const validation = hookJSONOutputSchema().safeParse(parsed)
387
- if (validation.success) {
388
- logForDebugging('Successfully parsed and validated hook JSON output')
389
- return { json: validation.data }
390
- }
391
- const errors = validation.error.issues
392
- .map(err => ` - ${err.path.join('.')}: ${err.message}`)
393
- .join('\n')
394
- return {
395
- validationError: `Hook JSON output validation failed:\n${errors}\n\nThe hook's output was: ${jsonStringify(parsed, null, 2)}`,
396
- }
397
- }
398
-
399
- function parseHookOutput(stdout: string): {
400
- json?: HookJSONOutput
401
- plainText?: string
402
- validationError?: string
403
- } {
404
- const trimmed = stdout.trim()
405
- if (!trimmed.startsWith('{')) {
406
- logForDebugging('Hook output does not start with {, treating as plain text')
407
- return { plainText: stdout }
408
- }
409
-
410
- try {
411
- const result = validateHookJson(trimmed)
412
- if ('json' in result) {
413
- return result
414
- }
415
- // For command hooks, include the schema hint in the error message
416
- const errorMessage = `${result.validationError}\n\nExpected schema:\n${jsonStringify(
417
- {
418
- continue: 'boolean (optional)',
419
- suppressOutput: 'boolean (optional)',
420
- stopReason: 'string (optional)',
421
- decision: '"approve" | "block" (optional)',
422
- reason: 'string (optional)',
423
- systemMessage: 'string (optional)',
424
- permissionDecision: '"allow" | "deny" | "ask" (optional)',
425
- hookSpecificOutput: {
426
- 'for PreToolUse': {
427
- hookEventName: '"PreToolUse"',
428
- permissionDecision: '"allow" | "deny" | "ask" (optional)',
429
- permissionDecisionReason: 'string (optional)',
430
- updatedInput: 'object (optional) - Modified tool input to use',
431
- },
432
- 'for UserPromptSubmit': {
433
- hookEventName: '"UserPromptSubmit"',
434
- additionalContext: 'string (required)',
435
- },
436
- 'for PostToolUse': {
437
- hookEventName: '"PostToolUse"',
438
- additionalContext: 'string (optional)',
439
- },
440
- },
441
- },
442
- null,
443
- 2,
444
- )}`
445
- logForDebugging(errorMessage)
446
- return { plainText: stdout, validationError: errorMessage }
447
- } catch (e) {
448
- logForDebugging(`Failed to parse hook output as JSON: ${e}`)
449
- return { plainText: stdout }
450
- }
451
- }
452
-
453
- function parseHttpHookOutput(body: string): {
454
- json?: HookJSONOutput
455
- validationError?: string
456
- } {
457
- const trimmed = body.trim()
458
-
459
- if (trimmed === '') {
460
- const validation = hookJSONOutputSchema().safeParse({})
461
- if (validation.success) {
462
- logForDebugging(
463
- 'HTTP hook returned empty body, treating as empty JSON object',
464
- )
465
- return { json: validation.data }
466
- }
467
- }
468
-
469
- if (!trimmed.startsWith('{')) {
470
- const validationError = `HTTP hook must return JSON, but got non-JSON response body: ${trimmed.length > 200 ? trimmed.slice(0, 200) + '\u2026' : trimmed}`
471
- logForDebugging(validationError)
472
- return { validationError }
473
- }
474
-
475
- try {
476
- const result = validateHookJson(trimmed)
477
- if ('json' in result) {
478
- return result
479
- }
480
- logForDebugging(result.validationError)
481
- return result
482
- } catch (e) {
483
- const validationError = `HTTP hook must return valid JSON, but parsing failed: ${e}`
484
- logForDebugging(validationError)
485
- return { validationError }
486
- }
487
- }
488
-
489
- function processHookJSONOutput({
490
- json,
491
- command,
492
- hookName,
493
- toolUseID,
494
- hookEvent,
495
- expectedHookEvent,
496
- stdout,
497
- stderr,
498
- exitCode,
499
- durationMs,
500
- }: {
501
- json: SyncHookJSONOutput
502
- command: string
503
- hookName: string
504
- toolUseID: string
505
- hookEvent: HookEvent
506
- expectedHookEvent?: HookEvent
507
- stdout?: string
508
- stderr?: string
509
- exitCode?: number
510
- durationMs?: number
511
- }): Partial<HookResult> {
512
- const result: Partial<HookResult> = {}
513
-
514
- // At this point we know it's a sync response
515
- const syncJson = json
516
-
517
- // Handle common elements
518
- if (syncJson.continue === false) {
519
- result.preventContinuation = true
520
- if (syncJson.stopReason) {
521
- result.stopReason = syncJson.stopReason
522
- }
523
- }
524
-
525
- if (json.decision) {
526
- switch (json.decision) {
527
- case 'approve':
528
- result.permissionBehavior = 'allow'
529
- break
530
- case 'block':
531
- result.permissionBehavior = 'deny'
532
- result.blockingError = {
533
- blockingError: json.reason || 'Blocked by hook',
534
- command,
535
- }
536
- break
537
- default:
538
- // Handle unknown decision types as errors
539
- throw new Error(
540
- `Unknown hook decision type: ${json.decision}. Valid types are: approve, block`,
541
- )
542
- }
543
- }
544
-
545
- // Handle systemMessage field
546
- if (json.systemMessage) {
547
- result.systemMessage = json.systemMessage
548
- }
549
-
550
- // Handle PreToolUse specific
551
- if (
552
- json.hookSpecificOutput?.hookEventName === 'PreToolUse' &&
553
- json.hookSpecificOutput.permissionDecision
554
- ) {
555
- switch (json.hookSpecificOutput.permissionDecision) {
556
- case 'allow':
557
- result.permissionBehavior = 'allow'
558
- break
559
- case 'deny':
560
- result.permissionBehavior = 'deny'
561
- result.blockingError = {
562
- blockingError: json.reason || 'Blocked by hook',
563
- command,
564
- }
565
- break
566
- case 'ask':
567
- result.permissionBehavior = 'ask'
568
- break
569
- default:
570
- // Handle unknown decision types as errors
571
- throw new Error(
572
- `Unknown hook permissionDecision type: ${json.hookSpecificOutput.permissionDecision}. Valid types are: allow, deny, ask`,
573
- )
574
- }
575
- }
576
- if (result.permissionBehavior !== undefined && json.reason !== undefined) {
577
- result.hookPermissionDecisionReason = json.reason
578
- }
579
-
580
- // Handle hookSpecificOutput
581
- if (json.hookSpecificOutput) {
582
- // Validate hook event name matches expected if provided
583
- if (
584
- expectedHookEvent &&
585
- json.hookSpecificOutput.hookEventName !== expectedHookEvent
586
- ) {
587
- throw new Error(
588
- `Hook returned incorrect event name: expected '${expectedHookEvent}' but got '${json.hookSpecificOutput.hookEventName}'. Full stdout: ${jsonStringify(json, null, 2)}`,
589
- )
590
- }
591
-
592
- switch (json.hookSpecificOutput.hookEventName) {
593
- case 'PreToolUse':
594
- // Override with more specific permission decision if provided
595
- if (json.hookSpecificOutput.permissionDecision) {
596
- switch (json.hookSpecificOutput.permissionDecision) {
597
- case 'allow':
598
- result.permissionBehavior = 'allow'
599
- break
600
- case 'deny':
601
- result.permissionBehavior = 'deny'
602
- result.blockingError = {
603
- blockingError:
604
- json.hookSpecificOutput.permissionDecisionReason ||
605
- json.reason ||
606
- 'Blocked by hook',
607
- command,
608
- }
609
- break
610
- case 'ask':
611
- result.permissionBehavior = 'ask'
612
- break
613
- }
614
- }
615
- result.hookPermissionDecisionReason =
616
- json.hookSpecificOutput.permissionDecisionReason
617
- // Extract updatedInput if provided
618
- if (json.hookSpecificOutput.updatedInput) {
619
- result.updatedInput = json.hookSpecificOutput.updatedInput
620
- }
621
- // Extract additionalContext if provided
622
- result.additionalContext = json.hookSpecificOutput.additionalContext
623
- break
624
- case 'UserPromptSubmit':
625
- result.additionalContext = json.hookSpecificOutput.additionalContext
626
- break
627
- case 'SessionStart':
628
- result.additionalContext = json.hookSpecificOutput.additionalContext
629
- result.initialUserMessage = json.hookSpecificOutput.initialUserMessage
630
- if (
631
- 'watchPaths' in json.hookSpecificOutput &&
632
- json.hookSpecificOutput.watchPaths
633
- ) {
634
- result.watchPaths = json.hookSpecificOutput.watchPaths
635
- }
636
- break
637
- case 'Setup':
638
- result.additionalContext = json.hookSpecificOutput.additionalContext
639
- break
640
- case 'SubagentStart':
641
- result.additionalContext = json.hookSpecificOutput.additionalContext
642
- break
643
- case 'PostToolUse':
644
- result.additionalContext = json.hookSpecificOutput.additionalContext
645
- // Extract updatedMCPToolOutput if provided
646
- if (json.hookSpecificOutput.updatedMCPToolOutput) {
647
- result.updatedMCPToolOutput =
648
- json.hookSpecificOutput.updatedMCPToolOutput
649
- }
650
- break
651
- case 'PostToolUseFailure':
652
- result.additionalContext = json.hookSpecificOutput.additionalContext
653
- break
654
- case 'PermissionDenied':
655
- result.retry = json.hookSpecificOutput.retry
656
- break
657
- case 'PermissionRequest':
658
- // Extract the permission request decision
659
- if (json.hookSpecificOutput.decision) {
660
- result.permissionRequestResult = json.hookSpecificOutput.decision
661
- // Also update permissionBehavior for consistency
662
- result.permissionBehavior =
663
- json.hookSpecificOutput.decision.behavior === 'allow'
664
- ? 'allow'
665
- : 'deny'
666
- if (
667
- json.hookSpecificOutput.decision.behavior === 'allow' &&
668
- json.hookSpecificOutput.decision.updatedInput
669
- ) {
670
- result.updatedInput = json.hookSpecificOutput.decision.updatedInput
671
- }
672
- }
673
- break
674
- case 'Elicitation':
675
- if (json.hookSpecificOutput.action) {
676
- result.elicitationResponse = {
677
- action: json.hookSpecificOutput.action,
678
- content: json.hookSpecificOutput.content as
679
- | ElicitationResponse['content']
680
- | undefined,
681
- }
682
- if (json.hookSpecificOutput.action === 'decline') {
683
- result.blockingError = {
684
- blockingError: json.reason || 'Elicitation denied by hook',
685
- command,
686
- }
687
- }
688
- }
689
- break
690
- case 'ElicitationResult':
691
- if (json.hookSpecificOutput.action) {
692
- result.elicitationResultResponse = {
693
- action: json.hookSpecificOutput.action,
694
- content: json.hookSpecificOutput.content as
695
- | ElicitationResponse['content']
696
- | undefined,
697
- }
698
- if (json.hookSpecificOutput.action === 'decline') {
699
- result.blockingError = {
700
- blockingError:
701
- json.reason || 'Elicitation result blocked by hook',
702
- command,
703
- }
704
- }
705
- }
706
- break
707
- }
708
- }
709
-
710
- return {
711
- ...result,
712
- message: result.blockingError
713
- ? createAttachmentMessage({
714
- type: 'hook_blocking_error',
715
- hookName,
716
- toolUseID,
717
- hookEvent,
718
- blockingError: result.blockingError,
719
- })
720
- : createAttachmentMessage({
721
- type: 'hook_success',
722
- hookName,
723
- toolUseID,
724
- hookEvent,
725
- // JSON-output hooks inject context via additionalContext →
726
- // hook_additional_context, not this field. Empty content suppresses
727
- // the trivial "X hook success: Success" system-reminder that
728
- // otherwise pollutes every turn (messages.ts:3577 skips on '').
729
- content: '',
730
- stdout,
731
- stderr,
732
- exitCode,
733
- command,
734
- durationMs,
735
- }),
736
- }
737
- }
738
-
739
- /**
740
- * Execute a command-based hook using bash or PowerShell.
741
- *
742
- * Shell resolution: hook.shell → 'bash'. PowerShell hooks spawn pwsh
743
- * with -NoProfile -NonInteractive -Command and skip bash-specific prep
744
- * (POSIX path conversion, .sh auto-prepend, CLAUDE_CODE_SHELL_PREFIX).
745
- * See docs/design/ps-shell-selection.md §5.1.
746
- */
747
- async function execCommandHook(
748
- hook: HookCommand & { type: 'command' },
749
- hookEvent: HookEvent | 'StatusLine' | 'FileSuggestion',
750
- hookName: string,
751
- jsonInput: string,
752
- signal: AbortSignal,
753
- hookId: string,
754
- hookIndex?: number,
755
- pluginRoot?: string,
756
- pluginId?: string,
757
- skillRoot?: string,
758
- forceSyncExecution?: boolean,
759
- requestPrompt?: (request: PromptRequest) => Promise<PromptResponse>,
760
- ): Promise<{
761
- stdout: string
762
- stderr: string
763
- output: string
764
- status: number
765
- aborted?: boolean
766
- backgrounded?: boolean
767
- }> {
768
- // Gated to once-per-session events to keep diag_log volume bounded.
769
- // started/completed live inside the try/finally so setup-path throws
770
- // don't orphan a started marker — that'd be indistinguishable from a hang.
771
- const shouldEmitDiag =
772
- hookEvent === 'SessionStart' ||
773
- hookEvent === 'Setup' ||
774
- hookEvent === 'SessionEnd'
775
- const diagStartMs = Date.now()
776
- let diagExitCode: number | undefined
777
- let diagAborted = false
778
-
779
- const isWindows = getPlatform() === 'windows'
780
-
781
- // --
782
- // Per-hook shell selection (phase 1 of docs/design/ps-shell-selection.md).
783
- // Resolution order: hook.shell → DEFAULT_HOOK_SHELL. The defaultShell
784
- // fallback (settings.defaultShell) is phase 2 — not wired yet.
785
- //
786
- // The bash path is the historical default and stays unchanged. The
787
- // PowerShell path deliberately skips the Windows-specific bash
788
- // accommodations (cygpath conversion, .sh auto-prepend, POSIX-quoted
789
- // SHELL_PREFIX).
790
- const shellType = hook.shell ?? DEFAULT_HOOK_SHELL
791
-
792
- const isPowerShell = shellType === 'powershell'
793
-
794
- // --
795
- // Windows bash path: hooks run via Git Bash (Cygwin), NOT cmd.exe.
796
- //
797
- // This means every path we put into env vars or substitute into the command
798
- // string MUST be a POSIX path (/c/Users/foo), not a Windows path
799
- // (C:\Users\foo or C:/Users/foo). Git Bash cannot resolve Windows paths.
800
- //
801
- // windowsPathToPosixPath() is pure-JS regex conversion (no cygpath shell-out):
802
- // C:\Users\foo -> /c/Users/foo, UNC preserved, slashes flipped. Memoized
803
- // (LRU-500) so repeated calls are cheap.
804
- //
805
- // PowerShell path: use native paths — skip the conversion entirely.
806
- // PowerShell expects Windows paths on Windows (and native paths on
807
- // Unix where pwsh is also available).
808
- const toHookPath =
809
- isWindows && !isPowerShell
810
- ? (p: string) => windowsPathToPosixPath(p)
811
- : (p: string) => p
812
-
813
- // Set CLAUDE_PROJECT_DIR to the stable project root (not the worktree path).
814
- // getProjectRoot() is never updated when entering a worktree, so hooks that
815
- // reference $CLAUDE_PROJECT_DIR always resolve relative to the real repo root.
816
- const projectDir = getProjectRoot()
817
-
818
- // Substitute ${CLAUDE_PLUGIN_ROOT} and ${user_config.X} in the command string.
819
- // Order matches MCP/LSP (plugin vars FIRST, then user config) so a user-
820
- // entered value containing the literal text ${CLAUDE_PLUGIN_ROOT} is treated
821
- // as opaque — not re-interpreted as a template.
822
- let command = hook.command
823
- let pluginOpts: ReturnType<typeof loadPluginOptions> | undefined
824
- if (pluginRoot) {
825
- // Plugin directory gone (orphan GC race, concurrent session deleted it):
826
- // throw so callers yield a non-blocking error. Running would fail — and
827
- // `python3 <missing>.py` exits 2, the hook protocol's "block" code, which
828
- // bricks UserPromptSubmit/Stop until restart. The pre-check is necessary
829
- // because exit-2-from-missing-script is indistinguishable from an
830
- // intentional block after spawn.
831
- if (!(await pathExists(pluginRoot))) {
832
- throw new Error(
833
- `Plugin directory does not exist: ${pluginRoot}` +
834
- (pluginId ? ` (${pluginId} — run /plugin to reinstall)` : ''),
835
- )
836
- }
837
- // Inline both ROOT and DATA substitution instead of calling
838
- // substitutePluginVariables(). That helper normalizes \ → / on Windows
839
- // unconditionally — correct for bash (toHookPath already produced /c/...
840
- // so it's a no-op) but wrong for PS where toHookPath is identity and we
841
- // want native C:\... backslashes. Inlining also lets us use the function-
842
- // form .replace() so paths containing $ aren't mangled by $-pattern
843
- // interpretation (rare but possible: \\server\c$\plugin).
844
- const rootPath = toHookPath(pluginRoot)
845
- command = command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, () => rootPath)
846
- if (pluginId) {
847
- const dataPath = toHookPath(getPluginDataDir(pluginId))
848
- command = command.replace(/\$\{CLAUDE_PLUGIN_DATA\}/g, () => dataPath)
849
- }
850
- if (pluginId) {
851
- pluginOpts = loadPluginOptions(pluginId)
852
- // Throws if a referenced key is missing — that means the hook uses a key
853
- // that's either not declared in manifest.userConfig or not yet configured.
854
- // Caught upstream like any other hook exec failure.
855
- command = substituteUserConfigVariables(command, pluginOpts)
856
- }
857
- }
858
-
859
- // On Windows (bash only), auto-prepend `bash` for .sh scripts so they
860
- // execute instead of opening in the default file handler. PowerShell
861
- // runs .ps1 files natively — no prepend needed.
862
- if (isWindows && !isPowerShell && command.trim().match(/\.sh(\s|$|")/)) {
863
- if (!command.trim().startsWith('bash ')) {
864
- command = `bash ${command}`
865
- }
866
- }
867
-
868
- // CLAUDE_CODE_SHELL_PREFIX wraps the command via POSIX quoting
869
- // (formatShellPrefixCommand uses shell-quote). This makes no sense for
870
- // PowerShell — see design §8.1. For now PS hooks ignore the prefix;
871
- // a CLAUDE_CODE_PS_SHELL_PREFIX (or shell-aware prefix) is a follow-up.
872
- const finalCommand =
873
- !isPowerShell && process.env.CLAUDE_CODE_SHELL_PREFIX
874
- ? formatShellPrefixCommand(process.env.CLAUDE_CODE_SHELL_PREFIX, command)
875
- : command
876
-
877
- const hookTimeoutMs = hook.timeout
878
- ? hook.timeout * 1000
879
- : TOOL_HOOK_EXECUTION_TIMEOUT_MS
880
-
881
- // Build env vars — all paths go through toHookPath for Windows POSIX conversion
882
- const envVars: NodeJS.ProcessEnv = {
883
- ...subprocessEnv(),
884
- CLAUDE_PROJECT_DIR: toHookPath(projectDir),
885
- }
886
-
887
- // Plugin and skill hooks both set CLAUDE_PLUGIN_ROOT (skills use the same
888
- // name for consistency — skills can migrate to plugins without code changes)
889
- if (pluginRoot) {
890
- envVars.CLAUDE_PLUGIN_ROOT = toHookPath(pluginRoot)
891
- if (pluginId) {
892
- envVars.CLAUDE_PLUGIN_DATA = toHookPath(getPluginDataDir(pluginId))
893
- }
894
- }
895
- // Expose plugin options as env vars too, so hooks can read them without
896
- // ${user_config.X} in the command string. Sensitive values included — hooks
897
- // run the user's own code, same trust boundary as reading keychain directly.
898
- if (pluginOpts) {
899
- for (const [key, value] of Object.entries(pluginOpts)) {
900
- // Sanitize non-identifier chars (bash can't ref $FOO-BAR). The schema
901
- // at schemas.ts:611 now constrains keys to /^[A-Za-z_]\w*$/ so this is
902
- // belt-and-suspenders, but cheap insurance if someone bypasses the schema.
903
- const envKey = key.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase()
904
- envVars[`CLAUDE_PLUGIN_OPTION_${envKey}`] = String(value)
905
- }
906
- }
907
- if (skillRoot) {
908
- envVars.CLAUDE_PLUGIN_ROOT = toHookPath(skillRoot)
909
- }
910
-
911
- // CLAUDE_ENV_FILE points to a .sh file that the hook writes env var
912
- // definitions into; getSessionEnvironmentScript() concatenates them and
913
- // bashProvider injects the content into bash commands. A PS hook would
914
- // naturally write PS syntax ($env:FOO = 'bar'), which bash can't parse.
915
- // Skip for PS — consistent with how .sh prepend and SHELL_PREFIX are
916
- // already bash-only above.
917
- if (
918
- !isPowerShell &&
919
- (hookEvent === 'SessionStart' ||
920
- hookEvent === 'Setup' ||
921
- hookEvent === 'CwdChanged' ||
922
- hookEvent === 'FileChanged') &&
923
- hookIndex !== undefined
924
- ) {
925
- envVars.CLAUDE_ENV_FILE = await getHookEnvFilePath(hookEvent, hookIndex)
926
- }
927
-
928
- // When agent worktrees are removed, getCwd() may return a deleted path via
929
- // AsyncLocalStorage. Validate before spawning since spawn() emits async
930
- // 'error' events for missing cwd rather than throwing synchronously.
931
- const hookCwd = getCwd()
932
- const safeCwd = (await pathExists(hookCwd)) ? hookCwd : getOriginalCwd()
933
- if (safeCwd !== hookCwd) {
934
- logForDebugging(
935
- `Hooks: cwd ${hookCwd} not found, falling back to original cwd`,
936
- { level: 'warn' },
937
- )
938
- }
939
-
940
- // --
941
- // Spawn. Two completely separate paths:
942
- //
943
- // Bash: spawn(cmd, [], { shell: <gitBashPath | true> }) — the shell
944
- // option makes Node pass the whole string to the shell for parsing.
945
- //
946
- // PowerShell: spawn(pwshPath, ['-NoProfile', '-NonInteractive',
947
- // '-Command', cmd]) — explicit argv, no shell option. -NoProfile
948
- // skips user profile scripts (faster, deterministic).
949
- // -NonInteractive fails fast instead of prompting.
950
- //
951
- // The Git Bash hard-exit in findGitBashPath() is still in place for
952
- // bash hooks. PowerShell hooks never call it, so a Windows user with
953
- // only pwsh and shell: 'powershell' on every hook could in theory run
954
- // without Git Bash — but init.ts still calls setShellIfWindows() on
955
- // startup, which will exit first. Relaxing that is phase 1 of the
956
- // design's implementation order (separate PR).
957
- let child: ChildProcessWithoutNullStreams
958
- if (shellType === 'powershell') {
959
- const pwshPath = await getCachedPowerShellPath()
960
- if (!pwshPath) {
961
- throw new Error(
962
- `Hook "${hook.command}" has shell: 'powershell' but no PowerShell ` +
963
- `executable (pwsh or powershell) was found on PATH. Install ` +
964
- `PowerShell, or remove "shell": "powershell" to use bash.`,
965
- )
966
- }
967
- child = spawn(pwshPath, buildPowerShellArgs(finalCommand), {
968
- env: envVars,
969
- cwd: safeCwd,
970
- // Prevent visible console window on Windows (no-op on other platforms)
971
- windowsHide: true,
972
- }) as ChildProcessWithoutNullStreams
973
- } else {
974
- // On Windows, use Git Bash explicitly (cmd.exe can't run bash syntax).
975
- // On other platforms, shell: true uses /bin/sh.
976
- const shell = isWindows ? findGitBashPath() : true
977
- child = spawn(finalCommand, [], {
978
- env: envVars,
979
- cwd: safeCwd,
980
- shell,
981
- // Prevent visible console window on Windows (no-op on other platforms)
982
- windowsHide: true,
983
- }) as ChildProcessWithoutNullStreams
984
- }
985
-
986
- // Hooks use pipe mode — stdout must be streamed into JS so we can parse
987
- // the first response line to detect async hooks ({"async": true}).
988
- const hookTaskOutput = new TaskOutput(`hook_${child.pid}`, null)
989
- const shellCommand = wrapSpawn(child, signal, hookTimeoutMs, hookTaskOutput)
990
- // Track whether shellCommand ownership was transferred (e.g., to async hook registry)
991
- let shellCommandTransferred = false
992
- // Track whether stdin has already been written (to avoid "write after end" errors)
993
- let stdinWritten = false
994
-
995
- if ((hook.async || hook.asyncRewake) && !forceSyncExecution) {
996
- const processId = `async_hook_${child.pid}`
997
- logForDebugging(
998
- `Hooks: Config-based async hook, backgrounding process ${processId}`,
999
- )
1000
-
1001
- // Write stdin before backgrounding so the hook receives its input.
1002
- // The trailing newline matches the sync path (L1000). Without it,
1003
- // bash `read -r line` returns exit 1 (EOF before delimiter) — the
1004
- // variable IS populated but `if read -r line; then ...` skips the
1005
- // branch. See gh-30509 / CC-161.
1006
- child.stdin.write(jsonInput + '\n', 'utf8')
1007
- child.stdin.end()
1008
- stdinWritten = true
1009
-
1010
- const backgrounded = executeInBackground({
1011
- processId,
1012
- hookId,
1013
- shellCommand,
1014
- asyncResponse: { async: true, asyncTimeout: hookTimeoutMs },
1015
- hookEvent,
1016
- hookName,
1017
- command: hook.command,
1018
- asyncRewake: hook.asyncRewake,
1019
- pluginId,
1020
- })
1021
- if (backgrounded) {
1022
- return {
1023
- stdout: '',
1024
- stderr: '',
1025
- output: '',
1026
- status: 0,
1027
- backgrounded: true,
1028
- }
1029
- }
1030
- }
1031
-
1032
- let stdout = ''
1033
- let stderr = ''
1034
- let output = ''
1035
-
1036
- // Set up output data collection with explicit UTF-8 encoding
1037
- child.stdout.setEncoding('utf8')
1038
- child.stderr.setEncoding('utf8')
1039
-
1040
- let initialResponseChecked = false
1041
-
1042
- let asyncResolve:
1043
- | ((result: {
1044
- stdout: string
1045
- stderr: string
1046
- output: string
1047
- status: number
1048
- }) => void)
1049
- | null = null
1050
- const childIsAsyncPromise = new Promise<{
1051
- stdout: string
1052
- stderr: string
1053
- output: string
1054
- status: number
1055
- aborted?: boolean
1056
- }>(resolve => {
1057
- asyncResolve = resolve
1058
- })
1059
-
1060
- // Track trimmed prompt-request lines we processed so we can strip them
1061
- // from final stdout by content match (no index tracking → no index drift)
1062
- const processedPromptLines = new Set<string>()
1063
- // Serialize async prompt handling so responses are sent in order
1064
- let promptChain = Promise.resolve()
1065
- // Line buffer for detecting prompt requests in streaming output
1066
- let lineBuffer = ''
1067
-
1068
- child.stdout.on('data', data => {
1069
- stdout += data
1070
- output += data
1071
-
1072
- // When requestPrompt is provided, parse stdout line-by-line for prompt requests
1073
- if (requestPrompt) {
1074
- lineBuffer += data
1075
- const lines = lineBuffer.split('\n')
1076
- lineBuffer = lines.pop() ?? '' // last element is an incomplete line
1077
-
1078
- for (const line of lines) {
1079
- const trimmed = line.trim()
1080
- if (!trimmed) continue
1081
-
1082
- try {
1083
- const parsed = jsonParse(trimmed)
1084
- const validation = promptRequestSchema().safeParse(parsed)
1085
- if (validation.success) {
1086
- processedPromptLines.add(trimmed)
1087
- logForDebugging(
1088
- `Hooks: Detected prompt request from hook: ${trimmed}`,
1089
- )
1090
- // Chain the async handling to serialize prompt responses
1091
- const promptReq = validation.data
1092
- const reqPrompt = requestPrompt
1093
- promptChain = promptChain.then(async () => {
1094
- try {
1095
- const response = await reqPrompt(promptReq)
1096
- child.stdin.write(jsonStringify(response) + '\n', 'utf8')
1097
- } catch (err) {
1098
- logForDebugging(`Hooks: Prompt request handling failed: ${err}`)
1099
- // User cancelled or prompt failed — close stdin so the hook
1100
- // process doesn't hang waiting for input
1101
- child.stdin.destroy()
1102
- }
1103
- })
1104
- continue
1105
- }
1106
- } catch {
1107
- // Not JSON, just a normal line
1108
- }
1109
- }
1110
- }
1111
-
1112
- // Check for async response on first line of output. The async protocol is:
1113
- // hook emits {"async":true,...} as its FIRST line, then its normal output.
1114
- // We must parse ONLY the first line — if the process is fast and writes more
1115
- // before this 'data' event fires, parsing the full accumulated stdout fails
1116
- // and an async hook blocks for its full duration instead of backgrounding.
1117
- if (!initialResponseChecked) {
1118
- const firstLine = firstLineOf(stdout).trim()
1119
- if (!firstLine.includes('}')) return
1120
- initialResponseChecked = true
1121
- logForDebugging(`Hooks: Checking first line for async: ${firstLine}`)
1122
- try {
1123
- const parsed = jsonParse(firstLine)
1124
- logForDebugging(
1125
- `Hooks: Parsed initial response: ${jsonStringify(parsed)}`,
1126
- )
1127
- if (isAsyncHookJSONOutput(parsed) && !forceSyncExecution) {
1128
- const processId = `async_hook_${child.pid}`
1129
- logForDebugging(
1130
- `Hooks: Detected async hook, backgrounding process ${processId}`,
1131
- )
1132
-
1133
- const backgrounded = executeInBackground({
1134
- processId,
1135
- hookId,
1136
- shellCommand,
1137
- asyncResponse: parsed,
1138
- hookEvent,
1139
- hookName,
1140
- command: hook.command,
1141
- pluginId,
1142
- })
1143
- if (backgrounded) {
1144
- shellCommandTransferred = true
1145
- asyncResolve?.({
1146
- stdout,
1147
- stderr,
1148
- output,
1149
- status: 0,
1150
- })
1151
- }
1152
- } else if (isAsyncHookJSONOutput(parsed) && forceSyncExecution) {
1153
- logForDebugging(
1154
- `Hooks: Detected async hook but forceSyncExecution is true, waiting for completion`,
1155
- )
1156
- } else {
1157
- logForDebugging(
1158
- `Hooks: Initial response is not async, continuing normal processing`,
1159
- )
1160
- }
1161
- } catch (e) {
1162
- logForDebugging(`Hooks: Failed to parse initial response as JSON: ${e}`)
1163
- }
1164
- }
1165
- })
1166
-
1167
- child.stderr.on('data', data => {
1168
- stderr += data
1169
- output += data
1170
- })
1171
-
1172
- const stopProgressInterval = startHookProgressInterval({
1173
- hookId,
1174
- hookName,
1175
- hookEvent,
1176
- getOutput: async () => ({ stdout, stderr, output }),
1177
- })
1178
-
1179
- // Wait for stdout and stderr streams to finish before considering output complete
1180
- // This prevents a race condition where 'close' fires before all 'data' events are processed
1181
- const stdoutEndPromise = new Promise<void>(resolve => {
1182
- child.stdout.on('end', () => resolve())
1183
- })
1184
-
1185
- const stderrEndPromise = new Promise<void>(resolve => {
1186
- child.stderr.on('end', () => resolve())
1187
- })
1188
-
1189
- // Write to stdin, making sure to handle EPIPE errors that can happen when
1190
- // the hook command exits before reading all input.
1191
- // Note: EPIPE handling is difficult to set up in testing since Bun and Node
1192
- // have different behaviors.
1193
- // TODO: Add tests for EPIPE handling.
1194
- // Skip if stdin was already written (e.g., by config-based async hook path)
1195
- const stdinWritePromise = stdinWritten
1196
- ? Promise.resolve()
1197
- : new Promise<void>((resolve, reject) => {
1198
- child.stdin.on('error', err => {
1199
- // When requestPrompt is provided, stdin stays open for prompt responses.
1200
- // EPIPE errors from later writes (after process exits) are expected -- suppress them.
1201
- if (!requestPrompt) {
1202
- reject(err)
1203
- } else {
1204
- logForDebugging(
1205
- `Hooks: stdin error during prompt flow (likely process exited): ${err}`,
1206
- )
1207
- }
1208
- })
1209
- // Explicitly specify UTF-8 encoding to ensure proper handling of Unicode characters
1210
- child.stdin.write(jsonInput + '\n', 'utf8')
1211
- // When requestPrompt is provided, keep stdin open for prompt responses
1212
- if (!requestPrompt) {
1213
- child.stdin.end()
1214
- }
1215
- resolve()
1216
- })
1217
-
1218
- // Create promise for child process error
1219
- const childErrorPromise = new Promise<never>((_, reject) => {
1220
- child.on('error', reject)
1221
- })
1222
-
1223
- // Create promise for child process close - but only resolve after streams end
1224
- // to ensure all output has been collected
1225
- const childClosePromise = new Promise<{
1226
- stdout: string
1227
- stderr: string
1228
- output: string
1229
- status: number
1230
- aborted?: boolean
1231
- }>(resolve => {
1232
- let exitCode: number | null = null
1233
-
1234
- child.on('close', code => {
1235
- exitCode = code ?? 1
1236
-
1237
- // Wait for both streams to end before resolving with the final output
1238
- void Promise.all([stdoutEndPromise, stderrEndPromise]).then(() => {
1239
- // Strip lines we processed as prompt requests so parseHookOutput
1240
- // only sees the final hook result. Content-matching against the set
1241
- // of actually-processed lines means prompt JSON can never leak
1242
- // through (fail-closed), regardless of line positioning.
1243
- const finalStdout =
1244
- processedPromptLines.size === 0
1245
- ? stdout
1246
- : stdout
1247
- .split('\n')
1248
- .filter(line => !processedPromptLines.has(line.trim()))
1249
- .join('\n')
1250
-
1251
- resolve({
1252
- stdout: finalStdout,
1253
- stderr,
1254
- output,
1255
- status: exitCode!,
1256
- aborted: signal.aborted,
1257
- })
1258
- })
1259
- })
1260
- })
1261
-
1262
- // Race between stdin write, async detection, and process completion
1263
- try {
1264
- if (shouldEmitDiag) {
1265
- logForDiagnosticsNoPII('info', 'hook_spawn_started', {
1266
- hook_event_name: hookEvent,
1267
- index: hookIndex,
1268
- })
1269
- }
1270
- await Promise.race([stdinWritePromise, childErrorPromise])
1271
-
1272
- // Wait for any pending prompt responses before resolving
1273
- const result = await Promise.race([
1274
- childIsAsyncPromise,
1275
- childClosePromise,
1276
- childErrorPromise,
1277
- ])
1278
- // Ensure all queued prompt responses have been sent
1279
- await promptChain
1280
- diagExitCode = result.status
1281
- diagAborted = result.aborted ?? false
1282
- return result
1283
- } catch (error) {
1284
- // Handle errors from stdin write or child process
1285
- const code = getErrnoCode(error)
1286
- diagExitCode = 1
1287
-
1288
- if (code === 'EPIPE') {
1289
- logForDebugging(
1290
- 'EPIPE error while writing to hook stdin (hook command likely closed early)',
1291
- )
1292
- const errMsg =
1293
- 'Hook command closed stdin before hook input was fully written (EPIPE)'
1294
- return {
1295
- stdout: '',
1296
- stderr: errMsg,
1297
- output: errMsg,
1298
- status: 1,
1299
- }
1300
- } else if (code === 'ABORT_ERR') {
1301
- diagAborted = true
1302
- return {
1303
- stdout: '',
1304
- stderr: 'Hook cancelled',
1305
- output: 'Hook cancelled',
1306
- status: 1,
1307
- aborted: true,
1308
- }
1309
- } else {
1310
- const errorMsg = errorMessage(error)
1311
- const errOutput = `Error occurred while executing hook command: ${errorMsg}`
1312
- return {
1313
- stdout: '',
1314
- stderr: errOutput,
1315
- output: errOutput,
1316
- status: 1,
1317
- }
1318
- }
1319
- } finally {
1320
- if (shouldEmitDiag) {
1321
- logForDiagnosticsNoPII('info', 'hook_spawn_completed', {
1322
- hook_event_name: hookEvent,
1323
- index: hookIndex,
1324
- duration_ms: Date.now() - diagStartMs,
1325
- exit_code: diagExitCode,
1326
- aborted: diagAborted,
1327
- })
1328
- }
1329
- stopProgressInterval()
1330
- // Clean up stream resources unless ownership was transferred (e.g., to async hook registry)
1331
- if (!shellCommandTransferred) {
1332
- shellCommand.cleanup()
1333
- }
1334
- }
1335
- }
1336
-
1337
- /**
1338
- * Check if a match query matches a hook matcher pattern
1339
- * @param matchQuery The query to match (e.g., 'Write', 'Edit', 'Bash')
1340
- * @param matcher The matcher pattern - can be:
1341
- * - Simple string for exact match (e.g., 'Write')
1342
- * - Pipe-separated list for multiple exact matches (e.g., 'Write|Edit')
1343
- * - Regex pattern (e.g., '^Write.*', '.*', '^(Write|Edit)$')
1344
- * @returns true if the query matches the pattern
1345
- */
1346
- function matchesPattern(matchQuery: string, matcher: string): boolean {
1347
- if (!matcher || matcher === '*') {
1348
- return true
1349
- }
1350
- // Check if it's a simple string or pipe-separated list (no regex special chars except |)
1351
- if (/^[a-zA-Z0-9_|]+$/.test(matcher)) {
1352
- // Handle pipe-separated exact matches
1353
- if (matcher.includes('|')) {
1354
- const patterns = matcher
1355
- .split('|')
1356
- .map(p => normalizeLegacyToolName(p.trim()))
1357
- return patterns.includes(matchQuery)
1358
- }
1359
- // Simple exact match
1360
- return matchQuery === normalizeLegacyToolName(matcher)
1361
- }
1362
-
1363
- // Otherwise treat as regex
1364
- try {
1365
- const regex = new RegExp(matcher)
1366
- if (regex.test(matchQuery)) {
1367
- return true
1368
- }
1369
- // Also test against legacy names so patterns like "^Task$" still match
1370
- for (const legacyName of getLegacyToolNames(matchQuery)) {
1371
- if (regex.test(legacyName)) {
1372
- return true
1373
- }
1374
- }
1375
- return false
1376
- } catch {
1377
- // If the regex is invalid, log error and return false
1378
- logForDebugging(`Invalid regex pattern in hook matcher: ${matcher}`)
1379
- return false
1380
- }
1381
- }
1382
-
1383
- type IfConditionMatcher = (ifCondition: string) => boolean
1384
-
1385
- /**
1386
- * Prepare a matcher for hook `if` conditions. Expensive work (tool lookup,
1387
- * Zod validation, tree-sitter parsing for Bash) happens once here; the
1388
- * returned closure is called per hook. Returns undefined for non-tool events.
1389
- */
1390
- async function prepareIfConditionMatcher(
1391
- hookInput: HookInput,
1392
- tools: Tools | undefined,
1393
- ): Promise<IfConditionMatcher | undefined> {
1394
- if (
1395
- hookInput.hook_event_name !== 'PreToolUse' &&
1396
- hookInput.hook_event_name !== 'PostToolUse' &&
1397
- hookInput.hook_event_name !== 'PostToolUseFailure' &&
1398
- hookInput.hook_event_name !== 'PermissionRequest'
1399
- ) {
1400
- return undefined
1401
- }
1402
-
1403
- const toolName = normalizeLegacyToolName(hookInput.tool_name)
1404
- const tool = tools && findToolByName(tools, hookInput.tool_name)
1405
- const input = tool?.inputSchema.safeParse(hookInput.tool_input)
1406
- const patternMatcher =
1407
- input?.success && tool?.preparePermissionMatcher
1408
- ? await tool.preparePermissionMatcher(input.data)
1409
- : undefined
1410
-
1411
- return ifCondition => {
1412
- const parsed = permissionRuleValueFromString(ifCondition)
1413
- if (normalizeLegacyToolName(parsed.toolName) !== toolName) {
1414
- return false
1415
- }
1416
- if (!parsed.ruleContent) {
1417
- return true
1418
- }
1419
- return patternMatcher ? patternMatcher(parsed.ruleContent) : false
1420
- }
1421
- }
1422
-
1423
- type FunctionHookMatcher = {
1424
- matcher: string
1425
- hooks: FunctionHook[]
1426
- }
1427
-
1428
- /**
1429
- * A hook paired with optional plugin context.
1430
- * Used when returning matched hooks so we can apply plugin env vars at execution time.
1431
- */
1432
- type MatchedHook = {
1433
- hook: HookCommand | HookCallback | FunctionHook
1434
- pluginRoot?: string
1435
- pluginId?: string
1436
- skillRoot?: string
1437
- hookSource?: string
1438
- }
1439
-
1440
- function isInternalHook(matched: MatchedHook): boolean {
1441
- return matched.hook.type === 'callback' && matched.hook.internal === true
1442
- }
1443
-
1444
- /**
1445
- * Build a dedup key for a matched hook, namespaced by source context.
1446
- *
1447
- * Settings-file hooks (no pluginRoot/skillRoot) share the '' prefix so the
1448
- * same command defined in user/project/local still collapses to one — the
1449
- * original intent of the dedup. Plugin/skill hooks get their root as the
1450
- * prefix, so two plugins sharing an unexpanded `${CLAUDE_PLUGIN_ROOT}/hook.sh`
1451
- * template don't collapse: after expansion they point to different files.
1452
- */
1453
- function hookDedupKey(m: MatchedHook, payload: string): string {
1454
- return `${m.pluginRoot ?? m.skillRoot ?? ''}\0${payload}`
1455
- }
1456
-
1457
- /**
1458
- * Build a map of {sanitizedPluginName: hookCount} from matched hooks.
1459
- * Only logs actual names for official marketplace plugins; others become 'third-party'.
1460
- */
1461
- function getPluginHookCounts(
1462
- hooks: MatchedHook[],
1463
- ): Record<string, number> | undefined {
1464
- const pluginHooks = hooks.filter(h => h.pluginId)
1465
- if (pluginHooks.length === 0) {
1466
- return undefined
1467
- }
1468
- const counts: Record<string, number> = {}
1469
- for (const h of pluginHooks) {
1470
- const atIndex = h.pluginId!.lastIndexOf('@')
1471
- const isOfficial =
1472
- atIndex > 0 &&
1473
- ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(h.pluginId!.slice(atIndex + 1))
1474
- const key = isOfficial ? h.pluginId! : 'third-party'
1475
- counts[key] = (counts[key] || 0) + 1
1476
- }
1477
- return counts
1478
- }
1479
-
1480
-
1481
- /**
1482
- * Build a map of {hookType: count} from matched hooks.
1483
- */
1484
- function getHookTypeCounts(hooks: MatchedHook[]): Record<string, number> {
1485
- const counts: Record<string, number> = {}
1486
- for (const h of hooks) {
1487
- counts[h.hook.type] = (counts[h.hook.type] || 0) + 1
1488
- }
1489
- return counts
1490
- }
1491
-
1492
- function getHooksConfig(
1493
- appState: AppState | undefined,
1494
- sessionId: string,
1495
- hookEvent: HookEvent,
1496
- ): Array<
1497
- | HookMatcher
1498
- | HookCallbackMatcher
1499
- | FunctionHookMatcher
1500
- | PluginHookMatcher
1501
- | SkillHookMatcher
1502
- | SessionDerivedHookMatcher
1503
- > {
1504
- // HookMatcher is a zod-stripped {matcher, hooks} so snapshot matchers can be
1505
- // pushed directly without re-wrapping.
1506
- const hooks: Array<
1507
- | HookMatcher
1508
- | HookCallbackMatcher
1509
- | FunctionHookMatcher
1510
- | PluginHookMatcher
1511
- | SkillHookMatcher
1512
- | SessionDerivedHookMatcher
1513
- > = [...(getHooksConfigFromSnapshot()?.[hookEvent] ?? [])]
1514
-
1515
- // Check if only managed hooks should run (used for both registered and session hooks)
1516
- const managedOnly = shouldAllowManagedHooksOnly()
1517
-
1518
- // Process registered hooks (SDK callbacks and plugin native hooks)
1519
- const registeredHooks = getRegisteredHooks()?.[hookEvent]
1520
- if (registeredHooks) {
1521
- for (const matcher of registeredHooks) {
1522
- // Skip plugin hooks when restricted to managed hooks only
1523
- // Plugin hooks have pluginRoot set, SDK callbacks do not
1524
- if (managedOnly && 'pluginRoot' in matcher) {
1525
- continue
1526
- }
1527
- hooks.push(matcher)
1528
- }
1529
- }
1530
-
1531
- // Merge session hooks for the current session only
1532
- // Function hooks (like structured output enforcement) must be scoped to their session
1533
- // to prevent hooks from one agent leaking to another (e.g., verification agent to main agent)
1534
- // Skip session hooks entirely when allowManagedHooksOnly is set —
1535
- // this prevents frontmatter hooks from agents/skills from bypassing the policy.
1536
- // strictPluginOnlyCustomization does NOT block here — it gates at the
1537
- // REGISTRATION sites (runAgent.ts:526 for agent frontmatter hooks) where
1538
- // agentDefinition.source is known. A blanket block here would also kill
1539
- // plugin-provided agents' frontmatter hooks, which is too broad.
1540
- // Also skip if appState not provided (for backwards compatibility)
1541
- if (!managedOnly && appState !== undefined) {
1542
- const sessionHooks = getSessionHooks(appState, sessionId, hookEvent).get(
1543
- hookEvent,
1544
- )
1545
- if (sessionHooks) {
1546
- // SessionDerivedHookMatcher already includes optional skillRoot
1547
- for (const matcher of sessionHooks) {
1548
- hooks.push(matcher)
1549
- }
1550
- }
1551
-
1552
- // Merge session function hooks separately (can't be persisted to HookMatcher format)
1553
- const sessionFunctionHooks = getSessionFunctionHooks(
1554
- appState,
1555
- sessionId,
1556
- hookEvent,
1557
- ).get(hookEvent)
1558
- if (sessionFunctionHooks) {
1559
- for (const matcher of sessionFunctionHooks) {
1560
- hooks.push(matcher)
1561
- }
1562
- }
1563
- }
1564
-
1565
- return hooks
1566
- }
1567
-
1568
- /**
1569
- * Lightweight existence check for hooks on a given event. Mirrors the sources
1570
- * assembled by getHooksConfig() but stops at the first hit without building
1571
- * the full merged config.
1572
- *
1573
- * Intentionally over-approximates: returns true if any matcher exists for the
1574
- * event, even if managed-only filtering or pattern matching would later
1575
- * discard it. A false positive just means we proceed to the full matching
1576
- * path; a false negative would skip a hook, so we err on the side of true.
1577
- *
1578
- * Used to skip createBaseHookInput (getTranscriptPathForSession path joins)
1579
- * and getMatchingHooks on hot paths where hooks are typically unconfigured.
1580
- * See hasInstructionsLoadedHook / hasWorktreeCreateHook for the same pattern.
1581
- */
1582
- function hasHookForEvent(
1583
- hookEvent: HookEvent,
1584
- appState: AppState | undefined,
1585
- sessionId: string,
1586
- ): boolean {
1587
- const snap = getHooksConfigFromSnapshot()?.[hookEvent]
1588
- if (snap && snap.length > 0) return true
1589
- const reg = getRegisteredHooks()?.[hookEvent]
1590
- if (reg && reg.length > 0) return true
1591
- if (appState?.sessionHooks.get(sessionId)?.hooks[hookEvent]) return true
1592
- return false
1593
- }
1594
-
1595
- /**
1596
- * Get hook commands that match the given query
1597
- * @param appState The current app state (optional for backwards compatibility)
1598
- * @param sessionId The current session ID (main session or agent ID)
1599
- * @param hookEvent The hook event
1600
- * @param hookInput The hook input for matching
1601
- * @returns Array of matched hooks with optional plugin context
1602
- */
1603
- export async function getMatchingHooks(
1604
- appState: AppState | undefined,
1605
- sessionId: string,
1606
- hookEvent: HookEvent,
1607
- hookInput: HookInput,
1608
- tools?: Tools,
1609
- ): Promise<MatchedHook[]> {
1610
- try {
1611
- const hookMatchers = getHooksConfig(appState, sessionId, hookEvent)
1612
-
1613
- // If you change the criteria below, then you must change
1614
- // src/utils/hooks/hooksConfigManager.ts as well.
1615
- let matchQuery: string | undefined = undefined
1616
- switch (hookInput.hook_event_name) {
1617
- case 'PreToolUse':
1618
- case 'PostToolUse':
1619
- case 'PostToolUseFailure':
1620
- case 'PermissionRequest':
1621
- case 'PermissionDenied':
1622
- matchQuery = hookInput.tool_name
1623
- break
1624
- case 'SessionStart':
1625
- matchQuery = hookInput.source
1626
- break
1627
- case 'Setup':
1628
- matchQuery = hookInput.trigger
1629
- break
1630
- case 'PreCompact':
1631
- case 'PostCompact':
1632
- matchQuery = hookInput.trigger
1633
- break
1634
- case 'Notification':
1635
- matchQuery = hookInput.notification_type
1636
- break
1637
- case 'SessionEnd':
1638
- matchQuery = hookInput.reason
1639
- break
1640
- case 'StopFailure':
1641
- matchQuery = hookInput.error
1642
- break
1643
- case 'SubagentStart':
1644
- matchQuery = hookInput.agent_type
1645
- break
1646
- case 'SubagentStop':
1647
- matchQuery = hookInput.agent_type
1648
- break
1649
- case 'TeammateIdle':
1650
- case 'TaskCreated':
1651
- case 'TaskCompleted':
1652
- break
1653
- case 'Elicitation':
1654
- matchQuery = hookInput.mcp_server_name
1655
- break
1656
- case 'ElicitationResult':
1657
- matchQuery = hookInput.mcp_server_name
1658
- break
1659
- case 'ConfigChange':
1660
- matchQuery = hookInput.source
1661
- break
1662
- case 'InstructionsLoaded':
1663
- matchQuery = hookInput.load_reason
1664
- break
1665
- case 'FileChanged':
1666
- matchQuery = basename(hookInput.file_path)
1667
- break
1668
- default:
1669
- break
1670
- }
1671
-
1672
- logForDebugging(
1673
- `Getting matching hook commands for ${hookEvent} with query: ${matchQuery}`,
1674
- { level: 'verbose' },
1675
- )
1676
- logForDebugging(`Found ${hookMatchers.length} hook matchers in settings`, {
1677
- level: 'verbose',
1678
- })
1679
-
1680
- // Extract hooks with their plugin context (if any)
1681
- const filteredMatchers = matchQuery
1682
- ? hookMatchers.filter(
1683
- matcher =>
1684
- !matcher.matcher || matchesPattern(matchQuery, matcher.matcher),
1685
- )
1686
- : hookMatchers
1687
-
1688
- const matchedHooks: MatchedHook[] = filteredMatchers.flatMap(matcher => {
1689
- // Check if this is a PluginHookMatcher (has pluginRoot) or SkillHookMatcher (has skillRoot)
1690
- const pluginRoot =
1691
- 'pluginRoot' in matcher ? matcher.pluginRoot : undefined
1692
- const pluginId = 'pluginId' in matcher ? matcher.pluginId : undefined
1693
- const skillRoot = 'skillRoot' in matcher ? matcher.skillRoot : undefined
1694
- const hookSource = pluginRoot
1695
- ? 'pluginName' in matcher
1696
- ? `plugin:${matcher.pluginName}`
1697
- : 'plugin'
1698
- : skillRoot
1699
- ? 'skillName' in matcher
1700
- ? `skill:${matcher.skillName}`
1701
- : 'skill'
1702
- : 'settings'
1703
- return matcher.hooks.map(hook => ({
1704
- hook,
1705
- pluginRoot,
1706
- pluginId,
1707
- skillRoot,
1708
- hookSource,
1709
- }))
1710
- })
1711
-
1712
- // Deduplicate hooks by command/prompt/url within the same source context.
1713
- // Key is namespaced by pluginRoot/skillRoot (see hookDedupKey above) so
1714
- // cross-plugin template collisions don't drop hooks (gh-29724).
1715
- //
1716
- // Note: new Map(entries) keeps the LAST entry on key collision, not first.
1717
- // For settings hooks this means the last-merged scope wins; for
1718
- // same-plugin duplicates the pluginRoot is identical so it doesn't matter.
1719
- // Fast-path: callback/function hooks don't need dedup (each is unique).
1720
- // Skip the 6-pass filter + 4×Map + 4×Array.from below when all hooks are
1721
- // callback/function — the common case for internal hooks like
1722
- // sessionFileAccessHooks/attributionHooks (44x faster in microbench).
1723
- if (
1724
- matchedHooks.every(
1725
- m => m.hook.type === 'callback' || m.hook.type === 'function',
1726
- )
1727
- ) {
1728
- return matchedHooks
1729
- }
1730
-
1731
- // Helper to extract the `if` condition from a hook for dedup keys.
1732
- // Hooks with different `if` conditions are distinct even if otherwise identical.
1733
- const getIfCondition = (hook: { if?: string }): string => hook.if ?? ''
1734
-
1735
- const uniqueCommandHooks = Array.from(
1736
- new Map(
1737
- matchedHooks
1738
- .filter(
1739
- (
1740
- m,
1741
- ): m is MatchedHook & { hook: HookCommand & { type: 'command' } } =>
1742
- m.hook.type === 'command',
1743
- )
1744
- // shell is part of identity: {command:'echo x', shell:'bash'}
1745
- // and {command:'echo x', shell:'powershell'} are distinct hooks,
1746
- // not duplicates. Default to 'bash' so legacy configs (no shell
1747
- // field) still dedup against explicit shell:'bash'.
1748
- .map(m => [
1749
- hookDedupKey(
1750
- m,
1751
- `${m.hook.shell ?? DEFAULT_HOOK_SHELL}\0${m.hook.command}\0${getIfCondition(m.hook)}`,
1752
- ),
1753
- m,
1754
- ]),
1755
- ).values(),
1756
- )
1757
- const uniquePromptHooks = Array.from(
1758
- new Map(
1759
- matchedHooks
1760
- .filter(m => m.hook.type === 'prompt')
1761
- .map(m => [
1762
- hookDedupKey(
1763
- m,
1764
- `${(m.hook as { prompt: string }).prompt}\0${getIfCondition(m.hook as { if?: string })}`,
1765
- ),
1766
- m,
1767
- ]),
1768
- ).values(),
1769
- )
1770
- const uniqueAgentHooks = Array.from(
1771
- new Map(
1772
- matchedHooks
1773
- .filter(m => m.hook.type === 'agent')
1774
- .map(m => [
1775
- hookDedupKey(
1776
- m,
1777
- `${(m.hook as { prompt: string }).prompt}\0${getIfCondition(m.hook as { if?: string })}`,
1778
- ),
1779
- m,
1780
- ]),
1781
- ).values(),
1782
- )
1783
- const uniqueHttpHooks = Array.from(
1784
- new Map(
1785
- matchedHooks
1786
- .filter(m => m.hook.type === 'http')
1787
- .map(m => [
1788
- hookDedupKey(
1789
- m,
1790
- `${(m.hook as { url: string }).url}\0${getIfCondition(m.hook as { if?: string })}`,
1791
- ),
1792
- m,
1793
- ]),
1794
- ).values(),
1795
- )
1796
- const callbackHooks = matchedHooks.filter(m => m.hook.type === 'callback')
1797
- // Function hooks don't need deduplication - each callback is unique
1798
- const functionHooks = matchedHooks.filter(m => m.hook.type === 'function')
1799
- const uniqueHooks = [
1800
- ...uniqueCommandHooks,
1801
- ...uniquePromptHooks,
1802
- ...uniqueAgentHooks,
1803
- ...uniqueHttpHooks,
1804
- ...callbackHooks,
1805
- ...functionHooks,
1806
- ]
1807
-
1808
- // Filter hooks based on their `if` condition. This allows hooks to specify
1809
- // conditions like "Bash(git *)" to only run for git commands, avoiding
1810
- // process spawning overhead for non-matching commands.
1811
- const hasIfCondition = uniqueHooks.some(
1812
- h =>
1813
- (h.hook.type === 'command' ||
1814
- h.hook.type === 'prompt' ||
1815
- h.hook.type === 'agent' ||
1816
- h.hook.type === 'http') &&
1817
- (h.hook as { if?: string }).if,
1818
- )
1819
- const ifMatcher = hasIfCondition
1820
- ? await prepareIfConditionMatcher(hookInput, tools)
1821
- : undefined
1822
- const ifFilteredHooks = uniqueHooks.filter(h => {
1823
- if (
1824
- h.hook.type !== 'command' &&
1825
- h.hook.type !== 'prompt' &&
1826
- h.hook.type !== 'agent' &&
1827
- h.hook.type !== 'http'
1828
- ) {
1829
- return true
1830
- }
1831
- const ifCondition = (h.hook as { if?: string }).if
1832
- if (!ifCondition) {
1833
- return true
1834
- }
1835
- if (!ifMatcher) {
1836
- logForDebugging(
1837
- `Hook if condition "${ifCondition}" cannot be evaluated for non-tool event ${hookInput.hook_event_name}`,
1838
- )
1839
- return false
1840
- }
1841
- if (ifMatcher(ifCondition)) {
1842
- return true
1843
- }
1844
- logForDebugging(
1845
- `Skipping hook due to if condition "${ifCondition}" not matching`,
1846
- )
1847
- return false
1848
- })
1849
-
1850
- // HTTP hooks are not supported for SessionStart/Setup events. In headless
1851
- // mode the sandbox ask callback deadlocks because the structuredInput
1852
- // consumer hasn't started yet when these hooks fire.
1853
- const filteredHooks =
1854
- hookEvent === 'SessionStart' || hookEvent === 'Setup'
1855
- ? ifFilteredHooks.filter(h => {
1856
- if (h.hook.type === 'http') {
1857
- logForDebugging(
1858
- `Skipping HTTP hook ${(h.hook as { url: string }).url} — HTTP hooks are not supported for ${hookEvent}`,
1859
- )
1860
- return false
1861
- }
1862
- return true
1863
- })
1864
- : ifFilteredHooks
1865
-
1866
- logForDebugging(
1867
- `Matched ${filteredHooks.length} unique hooks for query "${matchQuery || 'no match query'}" (${matchedHooks.length} before deduplication)`,
1868
- { level: 'verbose' },
1869
- )
1870
- return filteredHooks
1871
- } catch {
1872
- return []
1873
- }
1874
- }
1875
-
1876
- /**
1877
- * Format a list of blocking errors from a PreTool hook's configured commands.
1878
- * @param hookName The name of the hook (e.g., 'PreToolUse:Write', 'PreToolUse:Edit', 'PreToolUse:Bash')
1879
- * @param blockingErrors Array of blocking errors from hooks
1880
- * @returns Formatted blocking message
1881
- */
1882
- export function getPreToolHookBlockingMessage(
1883
- hookName: string,
1884
- blockingError: HookBlockingError,
1885
- ): string {
1886
- return `${hookName} hook error: ${blockingError.blockingError}`
1887
- }
1888
-
1889
- /**
1890
- * Format a list of blocking errors from a Stop hook's configured commands.
1891
- * @param blockingErrors Array of blocking errors from hooks
1892
- * @returns Formatted message to give feedback to the model
1893
- */
1894
- export function getStopHookMessage(blockingError: HookBlockingError): string {
1895
- return `Stop hook feedback:\n${blockingError.blockingError}`
1896
- }
1897
-
1898
- /**
1899
- * Format a blocking error from a TeammateIdle hook.
1900
- * @param blockingError The blocking error from the hook
1901
- * @returns Formatted message to give feedback to the model
1902
- */
1903
- export function getTeammateIdleHookMessage(
1904
- blockingError: HookBlockingError,
1905
- ): string {
1906
- return `TeammateIdle hook feedback:\n${blockingError.blockingError}`
1907
- }
1908
-
1909
- /**
1910
- * Format a blocking error from a TaskCreated hook.
1911
- * @param blockingError The blocking error from the hook
1912
- * @returns Formatted message to give feedback to the model
1913
- */
1914
- export function getTaskCreatedHookMessage(
1915
- blockingError: HookBlockingError,
1916
- ): string {
1917
- return `TaskCreated hook feedback:\n${blockingError.blockingError}`
1918
- }
1919
-
1920
- /**
1921
- * Format a blocking error from a TaskCompleted hook.
1922
- * @param blockingError The blocking error from the hook
1923
- * @returns Formatted message to give feedback to the model
1924
- */
1925
- export function getTaskCompletedHookMessage(
1926
- blockingError: HookBlockingError,
1927
- ): string {
1928
- return `TaskCompleted hook feedback:\n${blockingError.blockingError}`
1929
- }
1930
-
1931
- /**
1932
- * Format a list of blocking errors from a UserPromptSubmit hook's configured commands.
1933
- * @param blockingErrors Array of blocking errors from hooks
1934
- * @returns Formatted blocking message
1935
- */
1936
- export function getUserPromptSubmitHookBlockingMessage(
1937
- blockingError: HookBlockingError,
1938
- ): string {
1939
- return `UserPromptSubmit operation blocked by hook:\n${blockingError.blockingError}`
1940
- }
1941
- /**
1942
- * Common logic for executing hooks
1943
- * @param hookInput The structured hook input that will be validated and converted to JSON
1944
- * @param toolUseID The ID for tracking this hook execution
1945
- * @param matchQuery The query to match against hook matchers
1946
- * @param signal Optional AbortSignal to cancel hook execution
1947
- * @param timeoutMs Optional timeout in milliseconds for hook execution
1948
- * @param toolUseContext Optional ToolUseContext for prompt-based hooks (required if using prompt hooks)
1949
- * @param messages Optional conversation history for prompt/function hooks
1950
- * @returns Async generator that yields progress messages and hook results
1951
- */
1952
- async function* executeHooks({
1953
- hookInput,
1954
- toolUseID,
1955
- matchQuery,
1956
- signal,
1957
- timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
1958
- toolUseContext,
1959
- messages,
1960
- forceSyncExecution,
1961
- requestPrompt,
1962
- toolInputSummary,
1963
- }: {
1964
- hookInput: HookInput
1965
- toolUseID: string
1966
- matchQuery?: string
1967
- signal?: AbortSignal
1968
- timeoutMs?: number
1969
- toolUseContext?: ToolUseContext
1970
- messages?: Message[]
1971
- forceSyncExecution?: boolean
1972
- requestPrompt?: (
1973
- sourceName: string,
1974
- toolInputSummary?: string | null,
1975
- ) => (request: PromptRequest) => Promise<PromptResponse>
1976
- toolInputSummary?: string | null
1977
- }): AsyncGenerator<AggregatedHookResult> {
1978
- if (shouldDisableAllHooksIncludingManaged()) {
1979
- return
1980
- }
1981
-
1982
- if (isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
1983
- return
1984
- }
1985
-
1986
- const hookEvent = hookInput.hook_event_name
1987
- const hookName = matchQuery ? `${hookEvent}:${matchQuery}` : hookEvent
1988
-
1989
- // Bind the prompt callback to this hook's name and tool input summary so the UI can display context
1990
- const boundRequestPrompt = requestPrompt?.(hookName, toolInputSummary)
1991
-
1992
- // SECURITY: ALL hooks require workspace trust in interactive mode
1993
- // This centralized check prevents RCE vulnerabilities for all current and future hooks
1994
- if (shouldSkipHookDueToTrust()) {
1995
- logForDebugging(
1996
- `Skipping ${hookName} hook execution - workspace trust not accepted`,
1997
- )
1998
- return
1999
- }
2000
-
2001
- const appState = toolUseContext ? toolUseContext.getAppState() : undefined
2002
- // Use the agent's session ID if available, otherwise fall back to main session
2003
- const sessionId = toolUseContext?.agentId ?? getSessionId()
2004
- const matchingHooks = await getMatchingHooks(
2005
- appState,
2006
- sessionId,
2007
- hookEvent,
2008
- hookInput,
2009
- toolUseContext?.options?.tools,
2010
- )
2011
- if (matchingHooks.length === 0) {
2012
- return
2013
- }
2014
-
2015
- if (signal?.aborted) {
2016
- return
2017
- }
2018
-
2019
- const userHooks = matchingHooks.filter(h => !isInternalHook(h))
2020
- if (userHooks.length > 0) {
2021
- const pluginHookCounts = getPluginHookCounts(userHooks)
2022
- const hookTypeCounts = getHookTypeCounts(userHooks)
2023
- logEvent(`tengu_run_hook`, {
2024
- hookName:
2025
- hookName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
2026
- numCommands: userHooks.length,
2027
- hookTypeCounts: jsonStringify(
2028
- hookTypeCounts,
2029
- ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
2030
- ...(pluginHookCounts && {
2031
- pluginHookCounts: jsonStringify(
2032
- pluginHookCounts,
2033
- ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
2034
- }),
2035
- })
2036
- } else {
2037
- // Fast-path: all hooks are internal callbacks (sessionFileAccessHooks,
2038
- // attributionHooks). These return {} and don't use the abort signal, so we
2039
- // can skip span/progress/abortSignal/processHookJSONOutput/resultLoop.
2040
- // Measured: 6.01µs → ~1.8µs per PostToolUse hit (-70%).
2041
- const batchStartTime = Date.now()
2042
- const context = toolUseContext
2043
- ? {
2044
- getAppState: toolUseContext.getAppState,
2045
- updateAttributionState: toolUseContext.updateAttributionState,
2046
- }
2047
- : undefined
2048
- for (const [i, { hook }] of matchingHooks.entries()) {
2049
- if (hook.type === 'callback') {
2050
- await hook.callback(hookInput, toolUseID, signal, i, context)
2051
- }
2052
- }
2053
- const totalDurationMs = Date.now() - batchStartTime
2054
- getStatsStore()?.observe('hook_duration_ms', totalDurationMs)
2055
- addToTurnHookDuration(totalDurationMs)
2056
- logEvent(`tengu_repl_hook_finished`, {
2057
- hookName:
2058
- hookName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
2059
- numCommands: matchingHooks.length,
2060
- numSuccess: matchingHooks.length,
2061
- numBlocking: 0,
2062
- numNonBlockingError: 0,
2063
- numCancelled: 0,
2064
- totalDurationMs,
2065
- })
2066
- return
2067
- }
2068
-
2069
- // Collect hook definitions for beta tracing telemetry
2070
- const hookDefinitionsJson = isBetaTracingEnabled()
2071
- ? jsonStringify(getHookDefinitionsForTelemetry(matchingHooks))
2072
- : '[]'
2073
-
2074
- // Log hook execution start to OTEL (only for beta tracing)
2075
- if (isBetaTracingEnabled()) {
2076
- void logOTelEvent('hook_execution_start', {
2077
- hook_event: hookEvent,
2078
- hook_name: hookName,
2079
- num_hooks: String(matchingHooks.length),
2080
- managed_only: String(shouldAllowManagedHooksOnly()),
2081
- hook_definitions: hookDefinitionsJson,
2082
- hook_source: shouldAllowManagedHooksOnly() ? 'policySettings' : 'merged',
2083
- })
2084
- }
2085
-
2086
- // Start hook span for beta tracing
2087
- const hookSpan = startHookSpan(
2088
- hookEvent,
2089
- hookName,
2090
- matchingHooks.length,
2091
- hookDefinitionsJson,
2092
- )
2093
-
2094
- // Yield progress messages for each hook before execution
2095
- for (const { hook } of matchingHooks) {
2096
- yield {
2097
- message: {
2098
- type: 'progress',
2099
- data: {
2100
- type: 'hook_progress',
2101
- hookEvent,
2102
- hookName,
2103
- command: getHookDisplayText(hook),
2104
- ...(hook.type === 'prompt' && { promptText: hook.prompt }),
2105
- ...('statusMessage' in hook &&
2106
- hook.statusMessage != null && {
2107
- statusMessage: hook.statusMessage,
2108
- }),
2109
- },
2110
- parentToolUseID: toolUseID,
2111
- toolUseID,
2112
- timestamp: new Date().toISOString(),
2113
- uuid: randomUUID(),
2114
- },
2115
- }
2116
- }
2117
-
2118
- // Track wall-clock time for the entire hook batch
2119
- const batchStartTime = Date.now()
2120
-
2121
- // Lazy-once stringify of hookInput. Shared across all command/prompt/agent/http
2122
- // hooks in this batch (hookInput is never mutated). Callback/function hooks
2123
- // return before reaching this, so batches with only those pay no stringify cost.
2124
- let jsonInputResult:
2125
- | { ok: true; value: string }
2126
- | { ok: false; error: unknown }
2127
- | undefined
2128
- function getJsonInput() {
2129
- if (jsonInputResult !== undefined) {
2130
- return jsonInputResult
2131
- }
2132
- try {
2133
- return (jsonInputResult = { ok: true, value: jsonStringify(hookInput) })
2134
- } catch (error) {
2135
- logError(
2136
- Error(`Failed to stringify hook ${hookName} input`, { cause: error }),
2137
- )
2138
- return (jsonInputResult = { ok: false, error })
2139
- }
2140
- }
2141
-
2142
- // Run all hooks in parallel with individual timeouts
2143
- const hookPromises = matchingHooks.map(async function* (
2144
- { hook, pluginRoot, pluginId, skillRoot },
2145
- hookIndex,
2146
- ): AsyncGenerator<HookResult> {
2147
- if (hook.type === 'callback') {
2148
- const callbackTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs
2149
- const { signal: abortSignal, cleanup } = createCombinedAbortSignal(
2150
- signal,
2151
- { timeoutMs: callbackTimeoutMs },
2152
- )
2153
- yield executeHookCallback({
2154
- toolUseID,
2155
- hook,
2156
- hookEvent,
2157
- hookInput,
2158
- signal: abortSignal,
2159
- hookIndex,
2160
- toolUseContext,
2161
- }).finally(cleanup)
2162
- return
2163
- }
2164
-
2165
- if (hook.type === 'function') {
2166
- if (!messages) {
2167
- yield {
2168
- message: createAttachmentMessage({
2169
- type: 'hook_error_during_execution',
2170
- hookName,
2171
- toolUseID,
2172
- hookEvent,
2173
- content: 'Messages not provided for function hook',
2174
- }),
2175
- outcome: 'non_blocking_error',
2176
- hook,
2177
- }
2178
- return
2179
- }
2180
-
2181
- // Function hooks only come from session storage with callback embedded
2182
- yield executeFunctionHook({
2183
- hook,
2184
- messages,
2185
- hookName,
2186
- toolUseID,
2187
- hookEvent,
2188
- timeoutMs,
2189
- signal,
2190
- })
2191
- return
2192
- }
2193
-
2194
- // Command and prompt hooks need jsonInput
2195
- const commandTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs
2196
- const { signal: abortSignal, cleanup } = createCombinedAbortSignal(signal, {
2197
- timeoutMs: commandTimeoutMs,
2198
- })
2199
- const hookId = randomUUID()
2200
- const hookStartMs = Date.now()
2201
- const hookCommand = getHookDisplayText(hook)
2202
-
2203
- try {
2204
- const jsonInputRes = getJsonInput()
2205
- if (!jsonInputRes.ok) {
2206
- yield {
2207
- message: createAttachmentMessage({
2208
- type: 'hook_error_during_execution',
2209
- hookName,
2210
- toolUseID,
2211
- hookEvent,
2212
- content: `Failed to prepare hook input: ${errorMessage(jsonInputRes.error)}`,
2213
- command: hookCommand,
2214
- durationMs: Date.now() - hookStartMs,
2215
- }),
2216
- outcome: 'non_blocking_error',
2217
- hook,
2218
- }
2219
- cleanup()
2220
- return
2221
- }
2222
- const jsonInput = jsonInputRes.value
2223
-
2224
- if (hook.type === 'prompt') {
2225
- if (!toolUseContext) {
2226
- throw new Error(
2227
- 'ToolUseContext is required for prompt hooks. This is a bug.',
2228
- )
2229
- }
2230
- const promptResult = await execPromptHook(
2231
- hook,
2232
- hookName,
2233
- hookEvent,
2234
- jsonInput,
2235
- abortSignal,
2236
- toolUseContext,
2237
- messages,
2238
- toolUseID,
2239
- )
2240
- // Inject timing fields for hook visibility
2241
- if (promptResult.message?.type === 'attachment') {
2242
- const att = promptResult.message.attachment
2243
- if (
2244
- att.type === 'hook_success' ||
2245
- att.type === 'hook_non_blocking_error'
2246
- ) {
2247
- att.command = hookCommand
2248
- att.durationMs = Date.now() - hookStartMs
2249
- }
2250
- }
2251
- yield promptResult
2252
- cleanup?.()
2253
- return
2254
- }
2255
-
2256
- if (hook.type === 'agent') {
2257
- if (!toolUseContext) {
2258
- throw new Error(
2259
- 'ToolUseContext is required for agent hooks. This is a bug.',
2260
- )
2261
- }
2262
- if (!messages) {
2263
- throw new Error(
2264
- 'Messages are required for agent hooks. This is a bug.',
2265
- )
2266
- }
2267
- const agentResult = await execAgentHook(
2268
- hook,
2269
- hookName,
2270
- hookEvent,
2271
- jsonInput,
2272
- abortSignal,
2273
- toolUseContext,
2274
- toolUseID,
2275
- messages,
2276
- 'agent_type' in hookInput
2277
- ? (hookInput.agent_type as string)
2278
- : undefined,
2279
- )
2280
- // Inject timing fields for hook visibility
2281
- if (agentResult.message?.type === 'attachment') {
2282
- const att = agentResult.message.attachment
2283
- if (
2284
- att.type === 'hook_success' ||
2285
- att.type === 'hook_non_blocking_error'
2286
- ) {
2287
- att.command = hookCommand
2288
- att.durationMs = Date.now() - hookStartMs
2289
- }
2290
- }
2291
- yield agentResult
2292
- cleanup?.()
2293
- return
2294
- }
2295
-
2296
- if (hook.type === 'http') {
2297
- emitHookStarted(hookId, hookName, hookEvent)
2298
-
2299
- // execHttpHook manages its own timeout internally via hook.timeout or
2300
- // DEFAULT_HTTP_HOOK_TIMEOUT_MS, so pass the parent signal directly
2301
- // to avoid double-stacking timeouts with abortSignal.
2302
- const httpResult = await execHttpHook(
2303
- hook,
2304
- hookEvent,
2305
- jsonInput,
2306
- signal,
2307
- )
2308
- cleanup?.()
2309
-
2310
- if (httpResult.aborted) {
2311
- emitHookResponse({
2312
- hookId,
2313
- hookName,
2314
- hookEvent,
2315
- output: 'Hook cancelled',
2316
- stdout: '',
2317
- stderr: '',
2318
- exitCode: undefined,
2319
- outcome: 'cancelled',
2320
- })
2321
- yield {
2322
- message: createAttachmentMessage({
2323
- type: 'hook_cancelled',
2324
- hookName,
2325
- toolUseID,
2326
- hookEvent,
2327
- }),
2328
- outcome: 'cancelled' as const,
2329
- hook,
2330
- }
2331
- return
2332
- }
2333
-
2334
- if (httpResult.error || !httpResult.ok) {
2335
- const stderr =
2336
- httpResult.error || `HTTP ${httpResult.statusCode} from ${hook.url}`
2337
- emitHookResponse({
2338
- hookId,
2339
- hookName,
2340
- hookEvent,
2341
- output: stderr,
2342
- stdout: '',
2343
- stderr,
2344
- exitCode: httpResult.statusCode,
2345
- outcome: 'error',
2346
- })
2347
- yield {
2348
- message: createAttachmentMessage({
2349
- type: 'hook_non_blocking_error',
2350
- hookName,
2351
- toolUseID,
2352
- hookEvent,
2353
- stderr,
2354
- stdout: '',
2355
- exitCode: httpResult.statusCode ?? 0,
2356
- }),
2357
- outcome: 'non_blocking_error' as const,
2358
- hook,
2359
- }
2360
- return
2361
- }
2362
-
2363
- // HTTP hooks must return JSON — parse and validate through Zod
2364
- const { json: httpJson, validationError: httpValidationError } =
2365
- parseHttpHookOutput(httpResult.body)
2366
-
2367
- if (httpValidationError) {
2368
- emitHookResponse({
2369
- hookId,
2370
- hookName,
2371
- hookEvent,
2372
- output: httpResult.body,
2373
- stdout: httpResult.body,
2374
- stderr: `JSON validation failed: ${httpValidationError}`,
2375
- exitCode: httpResult.statusCode,
2376
- outcome: 'error',
2377
- })
2378
- yield {
2379
- message: createAttachmentMessage({
2380
- type: 'hook_non_blocking_error',
2381
- hookName,
2382
- toolUseID,
2383
- hookEvent,
2384
- stderr: `JSON validation failed: ${httpValidationError}`,
2385
- stdout: httpResult.body,
2386
- exitCode: httpResult.statusCode ?? 0,
2387
- }),
2388
- outcome: 'non_blocking_error' as const,
2389
- hook,
2390
- }
2391
- return
2392
- }
2393
-
2394
- if (httpJson && isAsyncHookJSONOutput(httpJson)) {
2395
- // Async response: treat as success (no further processing)
2396
- emitHookResponse({
2397
- hookId,
2398
- hookName,
2399
- hookEvent,
2400
- output: httpResult.body,
2401
- stdout: httpResult.body,
2402
- stderr: '',
2403
- exitCode: httpResult.statusCode,
2404
- outcome: 'success',
2405
- })
2406
- yield {
2407
- outcome: 'success' as const,
2408
- hook,
2409
- }
2410
- return
2411
- }
2412
-
2413
- if (httpJson) {
2414
- const processed = processHookJSONOutput({
2415
- json: httpJson,
2416
- command: hook.url,
2417
- hookName,
2418
- toolUseID,
2419
- hookEvent,
2420
- expectedHookEvent: hookEvent,
2421
- stdout: httpResult.body,
2422
- stderr: '',
2423
- exitCode: httpResult.statusCode,
2424
- })
2425
- emitHookResponse({
2426
- hookId,
2427
- hookName,
2428
- hookEvent,
2429
- output: httpResult.body,
2430
- stdout: httpResult.body,
2431
- stderr: '',
2432
- exitCode: httpResult.statusCode,
2433
- outcome: 'success',
2434
- })
2435
- yield {
2436
- ...processed,
2437
- outcome: 'success' as const,
2438
- hook,
2439
- }
2440
- return
2441
- }
2442
-
2443
- return
2444
- }
2445
-
2446
- emitHookStarted(hookId, hookName, hookEvent)
2447
-
2448
- const result = await execCommandHook(
2449
- hook,
2450
- hookEvent,
2451
- hookName,
2452
- jsonInput,
2453
- abortSignal,
2454
- hookId,
2455
- hookIndex,
2456
- pluginRoot,
2457
- pluginId,
2458
- skillRoot,
2459
- forceSyncExecution,
2460
- boundRequestPrompt,
2461
- )
2462
- cleanup?.()
2463
- const durationMs = Date.now() - hookStartMs
2464
-
2465
- if (result.backgrounded) {
2466
- yield {
2467
- outcome: 'success' as const,
2468
- hook,
2469
- }
2470
- return
2471
- }
2472
-
2473
- if (result.aborted) {
2474
- emitHookResponse({
2475
- hookId,
2476
- hookName,
2477
- hookEvent,
2478
- output: result.output,
2479
- stdout: result.stdout,
2480
- stderr: result.stderr,
2481
- exitCode: result.status,
2482
- outcome: 'cancelled',
2483
- })
2484
- yield {
2485
- message: createAttachmentMessage({
2486
- type: 'hook_cancelled',
2487
- hookName,
2488
- toolUseID,
2489
- hookEvent,
2490
- command: hookCommand,
2491
- durationMs,
2492
- }),
2493
- outcome: 'cancelled' as const,
2494
- hook,
2495
- }
2496
- return
2497
- }
2498
-
2499
- // Try JSON parsing first
2500
- const { json, plainText, validationError } = parseHookOutput(
2501
- result.stdout,
2502
- )
2503
-
2504
- if (validationError) {
2505
- emitHookResponse({
2506
- hookId,
2507
- hookName,
2508
- hookEvent,
2509
- output: result.output,
2510
- stdout: result.stdout,
2511
- stderr: `JSON validation failed: ${validationError}`,
2512
- exitCode: 1,
2513
- outcome: 'error',
2514
- })
2515
- yield {
2516
- message: createAttachmentMessage({
2517
- type: 'hook_non_blocking_error',
2518
- hookName,
2519
- toolUseID,
2520
- hookEvent,
2521
- stderr: `JSON validation failed: ${validationError}`,
2522
- stdout: result.stdout,
2523
- exitCode: 1,
2524
- command: hookCommand,
2525
- durationMs,
2526
- }),
2527
- outcome: 'non_blocking_error' as const,
2528
- hook,
2529
- }
2530
- return
2531
- }
2532
-
2533
- if (json) {
2534
- // Async responses were already backgrounded during execution
2535
- if (isAsyncHookJSONOutput(json)) {
2536
- yield {
2537
- outcome: 'success' as const,
2538
- hook,
2539
- }
2540
- return
2541
- }
2542
-
2543
- // Process JSON output
2544
- const processed = processHookJSONOutput({
2545
- json,
2546
- command: hookCommand,
2547
- hookName,
2548
- toolUseID,
2549
- hookEvent,
2550
- expectedHookEvent: hookEvent,
2551
- stdout: result.stdout,
2552
- stderr: result.stderr,
2553
- exitCode: result.status,
2554
- durationMs,
2555
- })
2556
-
2557
- // Handle suppressOutput (skip for async responses)
2558
- if (
2559
- isSyncHookJSONOutput(json) &&
2560
- !json.suppressOutput &&
2561
- plainText &&
2562
- result.status === 0
2563
- ) {
2564
- // Still show non-JSON output if not suppressed
2565
- const content = `${chalk.bold(hookName)} completed`
2566
- emitHookResponse({
2567
- hookId,
2568
- hookName,
2569
- hookEvent,
2570
- output: result.output,
2571
- stdout: result.stdout,
2572
- stderr: result.stderr,
2573
- exitCode: result.status,
2574
- outcome: 'success',
2575
- })
2576
- yield {
2577
- ...processed,
2578
- message:
2579
- processed.message ||
2580
- createAttachmentMessage({
2581
- type: 'hook_success',
2582
- hookName,
2583
- toolUseID,
2584
- hookEvent,
2585
- content,
2586
- stdout: result.stdout,
2587
- stderr: result.stderr,
2588
- exitCode: result.status,
2589
- command: hookCommand,
2590
- durationMs,
2591
- }),
2592
- outcome: 'success' as const,
2593
- hook,
2594
- }
2595
- return
2596
- }
2597
-
2598
- emitHookResponse({
2599
- hookId,
2600
- hookName,
2601
- hookEvent,
2602
- output: result.output,
2603
- stdout: result.stdout,
2604
- stderr: result.stderr,
2605
- exitCode: result.status,
2606
- outcome: result.status === 0 ? 'success' : 'error',
2607
- })
2608
- yield {
2609
- ...processed,
2610
- outcome: 'success' as const,
2611
- hook,
2612
- }
2613
- return
2614
- }
2615
-
2616
- // Fall back to existing logic for non-JSON output
2617
- if (result.status === 0) {
2618
- emitHookResponse({
2619
- hookId,
2620
- hookName,
2621
- hookEvent,
2622
- output: result.output,
2623
- stdout: result.stdout,
2624
- stderr: result.stderr,
2625
- exitCode: result.status,
2626
- outcome: 'success',
2627
- })
2628
- yield {
2629
- message: createAttachmentMessage({
2630
- type: 'hook_success',
2631
- hookName,
2632
- toolUseID,
2633
- hookEvent,
2634
- content: result.stdout.trim(),
2635
- stdout: result.stdout,
2636
- stderr: result.stderr,
2637
- exitCode: result.status,
2638
- command: hookCommand,
2639
- durationMs,
2640
- }),
2641
- outcome: 'success' as const,
2642
- hook,
2643
- }
2644
- return
2645
- }
2646
-
2647
- // Hooks with exit code 2 provide blocking feedback
2648
- if (result.status === 2) {
2649
- emitHookResponse({
2650
- hookId,
2651
- hookName,
2652
- hookEvent,
2653
- output: result.output,
2654
- stdout: result.stdout,
2655
- stderr: result.stderr,
2656
- exitCode: result.status,
2657
- outcome: 'error',
2658
- })
2659
- yield {
2660
- blockingError: {
2661
- blockingError: `[${hook.command}]: ${result.stderr || 'No stderr output'}`,
2662
- command: hook.command,
2663
- },
2664
- outcome: 'blocking' as const,
2665
- hook,
2666
- }
2667
- return
2668
- }
2669
-
2670
- // Any other non-zero exit code is a non-critical error that should just
2671
- // be shown to the user.
2672
- emitHookResponse({
2673
- hookId,
2674
- hookName,
2675
- hookEvent,
2676
- output: result.output,
2677
- stdout: result.stdout,
2678
- stderr: result.stderr,
2679
- exitCode: result.status,
2680
- outcome: 'error',
2681
- })
2682
- yield {
2683
- message: createAttachmentMessage({
2684
- type: 'hook_non_blocking_error',
2685
- hookName,
2686
- toolUseID,
2687
- hookEvent,
2688
- stderr: `Failed with non-blocking status code: ${result.stderr.trim() || 'No stderr output'}`,
2689
- stdout: result.stdout,
2690
- exitCode: result.status,
2691
- command: hookCommand,
2692
- durationMs,
2693
- }),
2694
- outcome: 'non_blocking_error' as const,
2695
- hook,
2696
- }
2697
- return
2698
- } catch (error) {
2699
- // Clean up on error
2700
- cleanup?.()
2701
-
2702
- const errorMessage =
2703
- error instanceof Error ? error.message : String(error)
2704
- emitHookResponse({
2705
- hookId,
2706
- hookName,
2707
- hookEvent,
2708
- output: `Failed to run: ${errorMessage}`,
2709
- stdout: '',
2710
- stderr: `Failed to run: ${errorMessage}`,
2711
- exitCode: 1,
2712
- outcome: 'error',
2713
- })
2714
- yield {
2715
- message: createAttachmentMessage({
2716
- type: 'hook_non_blocking_error',
2717
- hookName,
2718
- toolUseID,
2719
- hookEvent,
2720
- stderr: `Failed to run: ${errorMessage}`,
2721
- stdout: '',
2722
- exitCode: 1,
2723
- command: hookCommand,
2724
- durationMs: Date.now() - hookStartMs,
2725
- }),
2726
- outcome: 'non_blocking_error' as const,
2727
- hook,
2728
- }
2729
- return
2730
- }
2731
- })
2732
-
2733
- // Track outcomes for logging
2734
- const outcomes = {
2735
- success: 0,
2736
- blocking: 0,
2737
- non_blocking_error: 0,
2738
- cancelled: 0,
2739
- }
2740
-
2741
- let permissionBehavior: PermissionResult['behavior'] | undefined
2742
-
2743
- // Run all hooks in parallel and wait for all to complete
2744
- for await (const result of all(hookPromises)) {
2745
- outcomes[result.outcome]++
2746
-
2747
- // Check for preventContinuation early
2748
- if (result.preventContinuation) {
2749
- logForDebugging(
2750
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) requested preventContinuation`,
2751
- )
2752
- yield {
2753
- preventContinuation: true,
2754
- stopReason: result.stopReason,
2755
- }
2756
- }
2757
-
2758
- // Handle different result types
2759
- if (result.blockingError) {
2760
- yield {
2761
- blockingError: result.blockingError,
2762
- }
2763
- }
2764
-
2765
- if (result.message) {
2766
- yield { message: result.message }
2767
- }
2768
-
2769
- // Yield system message separately if present
2770
- if (result.systemMessage) {
2771
- yield {
2772
- message: createAttachmentMessage({
2773
- type: 'hook_system_message',
2774
- content: result.systemMessage,
2775
- hookName,
2776
- toolUseID,
2777
- hookEvent,
2778
- }),
2779
- }
2780
- }
2781
-
2782
- // Collect additional context from hooks
2783
- if (result.additionalContext) {
2784
- logForDebugging(
2785
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) provided additionalContext (${result.additionalContext.length} chars)`,
2786
- )
2787
- yield {
2788
- additionalContexts: [result.additionalContext],
2789
- }
2790
- }
2791
-
2792
- if (result.initialUserMessage) {
2793
- logForDebugging(
2794
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) provided initialUserMessage (${result.initialUserMessage.length} chars)`,
2795
- )
2796
- yield {
2797
- initialUserMessage: result.initialUserMessage,
2798
- }
2799
- }
2800
-
2801
- if (result.watchPaths && result.watchPaths.length > 0) {
2802
- logForDebugging(
2803
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) provided ${result.watchPaths.length} watchPaths`,
2804
- )
2805
- yield {
2806
- watchPaths: result.watchPaths,
2807
- }
2808
- }
2809
-
2810
- // Yield updatedMCPToolOutput if provided (from PostToolUse hooks)
2811
- if (result.updatedMCPToolOutput) {
2812
- logForDebugging(
2813
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) replaced MCP tool output`,
2814
- )
2815
- yield {
2816
- updatedMCPToolOutput: result.updatedMCPToolOutput,
2817
- }
2818
- }
2819
-
2820
- // Check for permission behavior with precedence: deny > ask > allow
2821
- if (result.permissionBehavior) {
2822
- logForDebugging(
2823
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) returned permissionDecision: ${result.permissionBehavior}${result.hookPermissionDecisionReason ? ` (reason: ${result.hookPermissionDecisionReason})` : ''}`,
2824
- )
2825
- // Apply precedence rules
2826
- switch (result.permissionBehavior) {
2827
- case 'deny':
2828
- // deny always takes precedence
2829
- permissionBehavior = 'deny'
2830
- break
2831
- case 'ask':
2832
- // ask takes precedence over allow but not deny
2833
- if (permissionBehavior !== 'deny') {
2834
- permissionBehavior = 'ask'
2835
- }
2836
- break
2837
- case 'allow':
2838
- // allow only if no other behavior set
2839
- if (!permissionBehavior) {
2840
- permissionBehavior = 'allow'
2841
- }
2842
- break
2843
- case 'passthrough':
2844
- // passthrough doesn't set permission behavior
2845
- break
2846
- }
2847
- }
2848
-
2849
- // Yield permission behavior and updatedInput if provided (from allow or ask behavior)
2850
- if (permissionBehavior !== undefined) {
2851
- const updatedInput =
2852
- result.updatedInput &&
2853
- (result.permissionBehavior === 'allow' ||
2854
- result.permissionBehavior === 'ask')
2855
- ? result.updatedInput
2856
- : undefined
2857
- if (updatedInput) {
2858
- logForDebugging(
2859
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) modified tool input keys: [${Object.keys(updatedInput).join(', ')}]`,
2860
- )
2861
- }
2862
- yield {
2863
- permissionBehavior,
2864
- hookPermissionDecisionReason: result.hookPermissionDecisionReason,
2865
- hookSource: matchingHooks.find(m => m.hook === result.hook)?.hookSource,
2866
- updatedInput,
2867
- }
2868
- }
2869
-
2870
- // Yield updatedInput separately for passthrough case (no permission decision)
2871
- // This allows hooks to modify input without making a permission decision
2872
- // Note: Check result.permissionBehavior (this hook's behavior), not the aggregated permissionBehavior
2873
- if (result.updatedInput && result.permissionBehavior === undefined) {
2874
- logForDebugging(
2875
- `Hook ${hookEvent} (${getHookDisplayText(result.hook)}) modified tool input keys: [${Object.keys(result.updatedInput).join(', ')}]`,
2876
- )
2877
- yield {
2878
- updatedInput: result.updatedInput,
2879
- }
2880
- }
2881
- // Yield permission request result if provided (from PermissionRequest hooks)
2882
- if (result.permissionRequestResult) {
2883
- yield {
2884
- permissionRequestResult: result.permissionRequestResult,
2885
- }
2886
- }
2887
- // Yield retry flag if provided (from PermissionDenied hooks)
2888
- if (result.retry) {
2889
- yield {
2890
- retry: result.retry,
2891
- }
2892
- }
2893
- // Yield elicitation response if provided (from Elicitation hooks)
2894
- if (result.elicitationResponse) {
2895
- yield {
2896
- elicitationResponse: result.elicitationResponse,
2897
- }
2898
- }
2899
- // Yield elicitation result response if provided (from ElicitationResult hooks)
2900
- if (result.elicitationResultResponse) {
2901
- yield {
2902
- elicitationResultResponse: result.elicitationResultResponse,
2903
- }
2904
- }
2905
-
2906
- // Invoke session hook callback if this is a command/prompt/function hook (not a callback hook)
2907
- if (appState && result.hook.type !== 'callback') {
2908
- const sessionId = getSessionId()
2909
- // Use empty string as matcher when matchQuery is undefined (e.g., for Stop hooks)
2910
- const matcher = matchQuery ?? ''
2911
- const hookEntry = getSessionHookCallback(
2912
- appState,
2913
- sessionId,
2914
- hookEvent,
2915
- matcher,
2916
- result.hook,
2917
- )
2918
- // Invoke onHookSuccess only on success outcome
2919
- if (hookEntry?.onHookSuccess && result.outcome === 'success') {
2920
- try {
2921
- hookEntry.onHookSuccess(result.hook, result as AggregatedHookResult)
2922
- } catch (error) {
2923
- logError(
2924
- Error('Session hook success callback failed', { cause: error }),
2925
- )
2926
- }
2927
- }
2928
- }
2929
- }
2930
-
2931
- const totalDurationMs = Date.now() - batchStartTime
2932
- getStatsStore()?.observe('hook_duration_ms', totalDurationMs)
2933
- addToTurnHookDuration(totalDurationMs)
2934
-
2935
- logEvent(`tengu_repl_hook_finished`, {
2936
- hookName:
2937
- hookName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
2938
- numCommands: matchingHooks.length,
2939
- numSuccess: outcomes.success,
2940
- numBlocking: outcomes.blocking,
2941
- numNonBlockingError: outcomes.non_blocking_error,
2942
- numCancelled: outcomes.cancelled,
2943
- totalDurationMs,
2944
- })
2945
-
2946
- // Log hook execution completion to OTEL (only for beta tracing)
2947
- if (isBetaTracingEnabled()) {
2948
- const hookDefinitionsComplete =
2949
- getHookDefinitionsForTelemetry(matchingHooks)
2950
-
2951
- void logOTelEvent('hook_execution_complete', {
2952
- hook_event: hookEvent,
2953
- hook_name: hookName,
2954
- num_hooks: String(matchingHooks.length),
2955
- num_success: String(outcomes.success),
2956
- num_blocking: String(outcomes.blocking),
2957
- num_non_blocking_error: String(outcomes.non_blocking_error),
2958
- num_cancelled: String(outcomes.cancelled),
2959
- managed_only: String(shouldAllowManagedHooksOnly()),
2960
- hook_definitions: jsonStringify(hookDefinitionsComplete),
2961
- hook_source: shouldAllowManagedHooksOnly() ? 'policySettings' : 'merged',
2962
- })
2963
- }
2964
-
2965
- // End hook span for beta tracing
2966
- endHookSpan(hookSpan, {
2967
- numSuccess: outcomes.success,
2968
- numBlocking: outcomes.blocking,
2969
- numNonBlockingError: outcomes.non_blocking_error,
2970
- numCancelled: outcomes.cancelled,
2971
- })
2972
- }
2973
-
2974
- export type HookOutsideReplResult = {
2975
- command: string
2976
- succeeded: boolean
2977
- output: string
2978
- blocked: boolean
2979
- watchPaths?: string[]
2980
- systemMessage?: string
2981
- }
2982
-
2983
- export function hasBlockingResult(results: HookOutsideReplResult[]): boolean {
2984
- return results.some(r => r.blocked)
2985
- }
2986
-
2987
- /**
2988
- * Execute hooks outside of the REPL (e.g. notifications, session end)
2989
- *
2990
- * Unlike executeHooks() which yields messages that are exposed to the model as
2991
- * system messages, this function only logs errors via logForDebugging (visible
2992
- * with --debug). Callers that need to surface errors to users should handle
2993
- * the returned results appropriately (e.g. executeSessionEndHooks writes to
2994
- * stderr during shutdown).
2995
- *
2996
- * @param getAppState Optional function to get the current app state (for session hooks)
2997
- * @param hookInput The structured hook input that will be validated and converted to JSON
2998
- * @param matchQuery The query to match against hook matchers
2999
- * @param signal Optional AbortSignal to cancel hook execution
3000
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3001
- * @returns Array of HookOutsideReplResult objects containing command, succeeded, and output
3002
- */
3003
- async function executeHooksOutsideREPL({
3004
- getAppState,
3005
- hookInput,
3006
- matchQuery,
3007
- signal,
3008
- timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3009
- }: {
3010
- getAppState?: () => AppState
3011
- hookInput: HookInput
3012
- matchQuery?: string
3013
- signal?: AbortSignal
3014
- timeoutMs: number
3015
- }): Promise<HookOutsideReplResult[]> {
3016
- if (isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
3017
- return []
3018
- }
3019
-
3020
- const hookEvent = hookInput.hook_event_name
3021
- const hookName = matchQuery ? `${hookEvent}:${matchQuery}` : hookEvent
3022
- if (shouldDisableAllHooksIncludingManaged()) {
3023
- logForDebugging(
3024
- `Skipping hooks for ${hookName} due to 'disableAllHooks' managed setting`,
3025
- )
3026
- return []
3027
- }
3028
-
3029
- // SECURITY: ALL hooks require workspace trust in interactive mode
3030
- // This centralized check prevents RCE vulnerabilities for all current and future hooks
3031
- if (shouldSkipHookDueToTrust()) {
3032
- logForDebugging(
3033
- `Skipping ${hookName} hook execution - workspace trust not accepted`,
3034
- )
3035
- return []
3036
- }
3037
-
3038
- const appState = getAppState ? getAppState() : undefined
3039
- // Use main session ID for outside-REPL hooks
3040
- const sessionId = getSessionId()
3041
- const matchingHooks = await getMatchingHooks(
3042
- appState,
3043
- sessionId,
3044
- hookEvent,
3045
- hookInput,
3046
- )
3047
- if (matchingHooks.length === 0) {
3048
- return []
3049
- }
3050
-
3051
- if (signal?.aborted) {
3052
- return []
3053
- }
3054
-
3055
- const userHooks = matchingHooks.filter(h => !isInternalHook(h))
3056
- if (userHooks.length > 0) {
3057
- const pluginHookCounts = getPluginHookCounts(userHooks)
3058
- const hookTypeCounts = getHookTypeCounts(userHooks)
3059
- logEvent(`tengu_run_hook`, {
3060
- hookName:
3061
- hookName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
3062
- numCommands: userHooks.length,
3063
- hookTypeCounts: jsonStringify(
3064
- hookTypeCounts,
3065
- ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
3066
- ...(pluginHookCounts && {
3067
- pluginHookCounts: jsonStringify(
3068
- pluginHookCounts,
3069
- ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
3070
- }),
3071
- })
3072
- }
3073
-
3074
- // Validate and stringify the hook input
3075
- let jsonInput: string
3076
- try {
3077
- jsonInput = jsonStringify(hookInput)
3078
- } catch (error) {
3079
- logError(error)
3080
- return []
3081
- }
3082
-
3083
- // Run all hooks in parallel with individual timeouts
3084
- const hookPromises = matchingHooks.map(
3085
- async ({ hook, pluginRoot, pluginId }, hookIndex) => {
3086
- // Handle callback hooks
3087
- if (hook.type === 'callback') {
3088
- const callbackTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs
3089
- const { signal: abortSignal, cleanup } = createCombinedAbortSignal(
3090
- signal,
3091
- { timeoutMs: callbackTimeoutMs },
3092
- )
3093
-
3094
- try {
3095
- const toolUseID = randomUUID()
3096
- const json = await hook.callback(
3097
- hookInput,
3098
- toolUseID,
3099
- abortSignal,
3100
- hookIndex,
3101
- )
3102
-
3103
- cleanup?.()
3104
-
3105
- if (isAsyncHookJSONOutput(json)) {
3106
- logForDebugging(
3107
- `${hookName} [callback] returned async response, returning empty output`,
3108
- )
3109
- return {
3110
- command: 'callback',
3111
- succeeded: true,
3112
- output: '',
3113
- blocked: false,
3114
- }
3115
- }
3116
-
3117
- const output =
3118
- hookEvent === 'WorktreeCreate' &&
3119
- isSyncHookJSONOutput(json) &&
3120
- json.hookSpecificOutput?.hookEventName === 'WorktreeCreate'
3121
- ? json.hookSpecificOutput.worktreePath
3122
- : json.systemMessage || ''
3123
- const blocked =
3124
- isSyncHookJSONOutput(json) && json.decision === 'block'
3125
-
3126
- logForDebugging(`${hookName} [callback] completed successfully`)
3127
-
3128
- return {
3129
- command: 'callback',
3130
- succeeded: true,
3131
- output,
3132
- blocked,
3133
- }
3134
- } catch (error) {
3135
- cleanup?.()
3136
-
3137
- const errorMessage =
3138
- error instanceof Error ? error.message : String(error)
3139
- logForDebugging(
3140
- `${hookName} [callback] failed to run: ${errorMessage}`,
3141
- { level: 'error' },
3142
- )
3143
- return {
3144
- command: 'callback',
3145
- succeeded: false,
3146
- output: errorMessage,
3147
- blocked: false,
3148
- }
3149
- }
3150
- }
3151
-
3152
- // TODO: Implement prompt stop hooks outside REPL
3153
- if (hook.type === 'prompt') {
3154
- return {
3155
- command: hook.prompt,
3156
- succeeded: false,
3157
- output: 'Prompt stop hooks are not yet supported outside REPL',
3158
- blocked: false,
3159
- }
3160
- }
3161
-
3162
- // TODO: Implement agent stop hooks outside REPL
3163
- if (hook.type === 'agent') {
3164
- return {
3165
- command: hook.prompt,
3166
- succeeded: false,
3167
- output: 'Agent stop hooks are not yet supported outside REPL',
3168
- blocked: false,
3169
- }
3170
- }
3171
-
3172
- // Function hooks require messages array (only available in REPL context)
3173
- // For -p mode Stop hooks, use executeStopHooks which supports function hooks
3174
- if (hook.type === 'function') {
3175
- logError(
3176
- new Error(
3177
- `Function hook reached executeHooksOutsideREPL for ${hookEvent}. Function hooks should only be used in REPL context (Stop hooks).`,
3178
- ),
3179
- )
3180
- return {
3181
- command: 'function',
3182
- succeeded: false,
3183
- output: 'Internal error: function hook executed outside REPL context',
3184
- blocked: false,
3185
- }
3186
- }
3187
-
3188
- // Handle HTTP hooks (no toolUseContext needed - just HTTP POST).
3189
- // execHttpHook handles its own timeout internally via hook.timeout or
3190
- // DEFAULT_HTTP_HOOK_TIMEOUT_MS, so we pass signal directly.
3191
- if (hook.type === 'http') {
3192
- try {
3193
- const httpResult = await execHttpHook(
3194
- hook,
3195
- hookEvent,
3196
- jsonInput,
3197
- signal,
3198
- )
3199
-
3200
- if (httpResult.aborted) {
3201
- logForDebugging(`${hookName} [${hook.url}] cancelled`)
3202
- return {
3203
- command: hook.url,
3204
- succeeded: false,
3205
- output: 'Hook cancelled',
3206
- blocked: false,
3207
- }
3208
- }
3209
-
3210
- if (httpResult.error || !httpResult.ok) {
3211
- const errMsg =
3212
- httpResult.error ||
3213
- `HTTP ${httpResult.statusCode} from ${hook.url}`
3214
- logForDebugging(`${hookName} [${hook.url}] failed: ${errMsg}`, {
3215
- level: 'error',
3216
- })
3217
- return {
3218
- command: hook.url,
3219
- succeeded: false,
3220
- output: errMsg,
3221
- blocked: false,
3222
- }
3223
- }
3224
-
3225
- // HTTP hooks must return JSON — parse and validate through Zod
3226
- const { json: httpJson, validationError: httpValidationError } =
3227
- parseHttpHookOutput(httpResult.body)
3228
- if (httpValidationError) {
3229
- throw new Error(httpValidationError)
3230
- }
3231
- if (httpJson && !isAsyncHookJSONOutput(httpJson)) {
3232
- logForDebugging(
3233
- `Parsed JSON output from HTTP hook: ${jsonStringify(httpJson)}`,
3234
- { level: 'verbose' },
3235
- )
3236
- }
3237
- const jsonBlocked =
3238
- httpJson &&
3239
- !isAsyncHookJSONOutput(httpJson) &&
3240
- isSyncHookJSONOutput(httpJson) &&
3241
- httpJson.decision === 'block'
3242
-
3243
- // WorktreeCreate's consumer reads `output` as the bare filesystem
3244
- // path. Command hooks provide it via stdout; http hooks provide it
3245
- // via hookSpecificOutput.worktreePath. Without worktreePath, emit ''
3246
- // so the consumer's length filter skips it instead of treating the
3247
- // raw '{}' body as a path.
3248
- const output =
3249
- hookEvent === 'WorktreeCreate'
3250
- ? httpJson &&
3251
- isSyncHookJSONOutput(httpJson) &&
3252
- httpJson.hookSpecificOutput?.hookEventName === 'WorktreeCreate'
3253
- ? httpJson.hookSpecificOutput.worktreePath
3254
- : ''
3255
- : httpResult.body
3256
-
3257
- return {
3258
- command: hook.url,
3259
- succeeded: true,
3260
- output,
3261
- blocked: !!jsonBlocked,
3262
- }
3263
- } catch (error) {
3264
- const errorMessage =
3265
- error instanceof Error ? error.message : String(error)
3266
- logForDebugging(
3267
- `${hookName} [${hook.url}] failed to run: ${errorMessage}`,
3268
- { level: 'error' },
3269
- )
3270
- return {
3271
- command: hook.url,
3272
- succeeded: false,
3273
- output: errorMessage,
3274
- blocked: false,
3275
- }
3276
- }
3277
- }
3278
-
3279
- // Handle command hooks
3280
- const commandTimeoutMs = hook.timeout ? hook.timeout * 1000 : timeoutMs
3281
- const { signal: abortSignal, cleanup } = createCombinedAbortSignal(
3282
- signal,
3283
- { timeoutMs: commandTimeoutMs },
3284
- )
3285
- try {
3286
- const result = await execCommandHook(
3287
- hook,
3288
- hookEvent,
3289
- hookName,
3290
- jsonInput,
3291
- abortSignal,
3292
- randomUUID(),
3293
- hookIndex,
3294
- pluginRoot,
3295
- pluginId,
3296
- )
3297
-
3298
- // Clear timeout if hook completes
3299
- cleanup?.()
3300
-
3301
- if (result.aborted) {
3302
- logForDebugging(`${hookName} [${hook.command}] cancelled`)
3303
- return {
3304
- command: hook.command,
3305
- succeeded: false,
3306
- output: 'Hook cancelled',
3307
- blocked: false,
3308
- }
3309
- }
3310
-
3311
- logForDebugging(
3312
- `${hookName} [${hook.command}] completed with status ${result.status}`,
3313
- )
3314
-
3315
- // Parse JSON for any messages to print out.
3316
- const { json, validationError } = parseHookOutput(result.stdout)
3317
- if (validationError) {
3318
- // Validation error is logged via logForDebugging and returned in output
3319
- throw new Error(validationError)
3320
- }
3321
- if (json && !isAsyncHookJSONOutput(json)) {
3322
- logForDebugging(
3323
- `Parsed JSON output from hook: ${jsonStringify(json)}`,
3324
- { level: 'verbose' },
3325
- )
3326
- }
3327
-
3328
- // Blocked if exit code 2 or JSON decision: 'block'
3329
- const jsonBlocked =
3330
- json &&
3331
- !isAsyncHookJSONOutput(json) &&
3332
- isSyncHookJSONOutput(json) &&
3333
- json.decision === 'block'
3334
- const blocked = result.status === 2 || !!jsonBlocked
3335
-
3336
- // For successful hooks (exit code 0), use stdout; for failed hooks, use stderr
3337
- const output =
3338
- result.status === 0 ? result.stdout || '' : result.stderr || ''
3339
-
3340
- const watchPaths =
3341
- json &&
3342
- isSyncHookJSONOutput(json) &&
3343
- json.hookSpecificOutput &&
3344
- 'watchPaths' in json.hookSpecificOutput
3345
- ? json.hookSpecificOutput.watchPaths
3346
- : undefined
3347
-
3348
- const systemMessage =
3349
- json && isSyncHookJSONOutput(json) ? json.systemMessage : undefined
3350
-
3351
- return {
3352
- command: hook.command,
3353
- succeeded: result.status === 0,
3354
- output,
3355
- blocked,
3356
- watchPaths,
3357
- systemMessage,
3358
- }
3359
- } catch (error) {
3360
- // Clean up on error
3361
- cleanup?.()
3362
-
3363
- const errorMessage =
3364
- error instanceof Error ? error.message : String(error)
3365
- logForDebugging(
3366
- `${hookName} [${hook.command}] failed to run: ${errorMessage}`,
3367
- { level: 'error' },
3368
- )
3369
- return {
3370
- command: hook.command,
3371
- succeeded: false,
3372
- output: errorMessage,
3373
- blocked: false,
3374
- }
3375
- }
3376
- },
3377
- )
3378
-
3379
- // Wait for all hooks to complete and collect results
3380
- return await Promise.all(hookPromises)
3381
- }
3382
-
3383
- /**
3384
- * Execute pre-tool hooks if configured
3385
- * @param toolName The name of the tool (e.g., 'Write', 'Edit', 'Bash')
3386
- * @param toolUseID The ID of the tool use
3387
- * @param toolInput The input that will be passed to the tool
3388
- * @param permissionMode Optional permission mode from toolPermissionContext
3389
- * @param signal Optional AbortSignal to cancel hook execution
3390
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3391
- * @param toolUseContext Optional ToolUseContext for prompt-based hooks
3392
- * @returns Async generator that yields progress messages and returns blocking errors
3393
- */
3394
- export async function* executePreToolHooks<ToolInput>(
3395
- toolName: string,
3396
- toolUseID: string,
3397
- toolInput: ToolInput,
3398
- toolUseContext: ToolUseContext,
3399
- permissionMode?: string,
3400
- signal?: AbortSignal,
3401
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3402
- requestPrompt?: (
3403
- sourceName: string,
3404
- toolInputSummary?: string | null,
3405
- ) => (request: PromptRequest) => Promise<PromptResponse>,
3406
- toolInputSummary?: string | null,
3407
- ): AsyncGenerator<AggregatedHookResult> {
3408
- const appState = toolUseContext.getAppState()
3409
- const sessionId = toolUseContext.agentId ?? getSessionId()
3410
- if (!hasHookForEvent('PreToolUse', appState, sessionId)) {
3411
- return
3412
- }
3413
-
3414
- logForDebugging(`executePreToolHooks called for tool: ${toolName}`, {
3415
- level: 'verbose',
3416
- })
3417
-
3418
- const hookInput: PreToolUseHookInput = {
3419
- ...createBaseHookInput(permissionMode, undefined, toolUseContext),
3420
- hook_event_name: 'PreToolUse',
3421
- tool_name: toolName,
3422
- tool_input: toolInput,
3423
- tool_use_id: toolUseID,
3424
- }
3425
-
3426
- yield* executeHooks({
3427
- hookInput,
3428
- toolUseID,
3429
- matchQuery: toolName,
3430
- signal,
3431
- timeoutMs,
3432
- toolUseContext,
3433
- requestPrompt,
3434
- toolInputSummary,
3435
- })
3436
- }
3437
-
3438
- /**
3439
- * Execute post-tool hooks if configured
3440
- * @param toolName The name of the tool (e.g., 'Write', 'Edit', 'Bash')
3441
- * @param toolUseID The ID of the tool use
3442
- * @param toolInput The input that was passed to the tool
3443
- * @param toolResponse The response from the tool
3444
- * @param toolUseContext ToolUseContext for prompt-based hooks
3445
- * @param permissionMode Optional permission mode from toolPermissionContext
3446
- * @param signal Optional AbortSignal to cancel hook execution
3447
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3448
- * @returns Async generator that yields progress messages and blocking errors for automated feedback
3449
- */
3450
- export async function* executePostToolHooks<ToolInput, ToolResponse>(
3451
- toolName: string,
3452
- toolUseID: string,
3453
- toolInput: ToolInput,
3454
- toolResponse: ToolResponse,
3455
- toolUseContext: ToolUseContext,
3456
- permissionMode?: string,
3457
- signal?: AbortSignal,
3458
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3459
- ): AsyncGenerator<AggregatedHookResult> {
3460
- const hookInput: PostToolUseHookInput = {
3461
- ...createBaseHookInput(permissionMode, undefined, toolUseContext),
3462
- hook_event_name: 'PostToolUse',
3463
- tool_name: toolName,
3464
- tool_input: toolInput,
3465
- tool_response: toolResponse,
3466
- tool_use_id: toolUseID,
3467
- }
3468
-
3469
- yield* executeHooks({
3470
- hookInput,
3471
- toolUseID,
3472
- matchQuery: toolName,
3473
- signal,
3474
- timeoutMs,
3475
- toolUseContext,
3476
- })
3477
- }
3478
-
3479
- /**
3480
- * Execute post-tool-use-failure hooks if configured
3481
- * @param toolName The name of the tool (e.g., 'Write', 'Edit', 'Bash')
3482
- * @param toolUseID The ID of the tool use
3483
- * @param toolInput The input that was passed to the tool
3484
- * @param error The error message from the failed tool call
3485
- * @param toolUseContext ToolUseContext for prompt-based hooks
3486
- * @param isInterrupt Whether the tool was interrupted by user
3487
- * @param permissionMode Optional permission mode from toolPermissionContext
3488
- * @param signal Optional AbortSignal to cancel hook execution
3489
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3490
- * @returns Async generator that yields progress messages and blocking errors
3491
- */
3492
- export async function* executePostToolUseFailureHooks<ToolInput>(
3493
- toolName: string,
3494
- toolUseID: string,
3495
- toolInput: ToolInput,
3496
- error: string,
3497
- toolUseContext: ToolUseContext,
3498
- isInterrupt?: boolean,
3499
- permissionMode?: string,
3500
- signal?: AbortSignal,
3501
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3502
- ): AsyncGenerator<AggregatedHookResult> {
3503
- const appState = toolUseContext.getAppState()
3504
- const sessionId = toolUseContext.agentId ?? getSessionId()
3505
- if (!hasHookForEvent('PostToolUseFailure', appState, sessionId)) {
3506
- return
3507
- }
3508
-
3509
- const hookInput: PostToolUseFailureHookInput = {
3510
- ...createBaseHookInput(permissionMode, undefined, toolUseContext),
3511
- hook_event_name: 'PostToolUseFailure',
3512
- tool_name: toolName,
3513
- tool_input: toolInput,
3514
- tool_use_id: toolUseID,
3515
- error,
3516
- is_interrupt: isInterrupt,
3517
- }
3518
-
3519
- yield* executeHooks({
3520
- hookInput,
3521
- toolUseID,
3522
- matchQuery: toolName,
3523
- signal,
3524
- timeoutMs,
3525
- toolUseContext,
3526
- })
3527
- }
3528
-
3529
- export async function* executePermissionDeniedHooks<ToolInput>(
3530
- toolName: string,
3531
- toolUseID: string,
3532
- toolInput: ToolInput,
3533
- reason: string,
3534
- toolUseContext: ToolUseContext,
3535
- permissionMode?: string,
3536
- signal?: AbortSignal,
3537
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3538
- ): AsyncGenerator<AggregatedHookResult> {
3539
- const appState = toolUseContext.getAppState()
3540
- const sessionId = toolUseContext.agentId ?? getSessionId()
3541
- if (!hasHookForEvent('PermissionDenied', appState, sessionId)) {
3542
- return
3543
- }
3544
-
3545
- const hookInput: PermissionDeniedHookInput = {
3546
- ...createBaseHookInput(permissionMode, undefined, toolUseContext),
3547
- hook_event_name: 'PermissionDenied',
3548
- tool_name: toolName,
3549
- tool_input: toolInput,
3550
- tool_use_id: toolUseID,
3551
- reason,
3552
- }
3553
-
3554
- yield* executeHooks({
3555
- hookInput,
3556
- toolUseID,
3557
- matchQuery: toolName,
3558
- signal,
3559
- timeoutMs,
3560
- toolUseContext,
3561
- })
3562
- }
3563
-
3564
- /**
3565
- * Execute notification hooks if configured
3566
- * @param notificationData The notification data to pass to hooks
3567
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3568
- * @returns Promise that resolves when all hooks complete
3569
- */
3570
- export async function executeNotificationHooks(
3571
- notificationData: {
3572
- message: string
3573
- title?: string
3574
- notificationType: string
3575
- },
3576
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3577
- ): Promise<void> {
3578
- const { message, title, notificationType } = notificationData
3579
- const hookInput: NotificationHookInput = {
3580
- ...createBaseHookInput(undefined),
3581
- hook_event_name: 'Notification',
3582
- message,
3583
- title,
3584
- notification_type: notificationType,
3585
- }
3586
-
3587
- await executeHooksOutsideREPL({
3588
- hookInput,
3589
- timeoutMs,
3590
- matchQuery: notificationType,
3591
- })
3592
- }
3593
-
3594
- export async function executeStopFailureHooks(
3595
- lastMessage: AssistantMessage,
3596
- toolUseContext?: ToolUseContext,
3597
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3598
- ): Promise<void> {
3599
- const appState = toolUseContext?.getAppState()
3600
- // executeHooksOutsideREPL hardcodes main sessionId (:2738). Agent frontmatter
3601
- // hooks (registerFrontmatterHooks) key by agentId; gating with agentId here
3602
- // would pass the gate but fail execution. Align gate with execution.
3603
- const sessionId = getSessionId()
3604
- if (!hasHookForEvent('StopFailure', appState, sessionId)) return
3605
-
3606
- const lastAssistantText =
3607
- extractTextContent(lastMessage.message.content, '\n').trim() || undefined
3608
-
3609
- // Some createAssistantAPIErrorMessage call sites omit `error` (e.g.
3610
- // image-size at errors.ts:431). Default to 'unknown' so matcher filtering
3611
- // at getMatchingHooks:1525 always applies.
3612
- const error = lastMessage.error ?? 'unknown'
3613
- const hookInput: StopFailureHookInput = {
3614
- ...createBaseHookInput(undefined, undefined, toolUseContext),
3615
- hook_event_name: 'StopFailure',
3616
- error,
3617
- error_details: lastMessage.errorDetails,
3618
- last_assistant_message: lastAssistantText,
3619
- }
3620
-
3621
- await executeHooksOutsideREPL({
3622
- getAppState: toolUseContext?.getAppState,
3623
- hookInput,
3624
- timeoutMs,
3625
- matchQuery: error,
3626
- })
3627
- }
3628
-
3629
- /**
3630
- * Execute stop hooks if configured
3631
- * @param toolUseContext ToolUseContext for prompt-based hooks
3632
- * @param permissionMode permission mode from toolPermissionContext
3633
- * @param signal AbortSignal to cancel hook execution
3634
- * @param stopHookActive Whether this call is happening within another stop hook
3635
- * @param isSubagent Whether the current execution context is a subagent
3636
- * @param messages Optional conversation history for prompt/function hooks
3637
- * @returns Async generator that yields progress messages and blocking errors
3638
- */
3639
- export async function* executeStopHooks(
3640
- permissionMode?: string,
3641
- signal?: AbortSignal,
3642
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3643
- stopHookActive: boolean = false,
3644
- subagentId?: AgentId,
3645
- toolUseContext?: ToolUseContext,
3646
- messages?: Message[],
3647
- agentType?: string,
3648
- requestPrompt?: (
3649
- sourceName: string,
3650
- toolInputSummary?: string | null,
3651
- ) => (request: PromptRequest) => Promise<PromptResponse>,
3652
- ): AsyncGenerator<AggregatedHookResult> {
3653
- const hookEvent = subagentId ? 'SubagentStop' : 'Stop'
3654
- const appState = toolUseContext?.getAppState()
3655
- const sessionId = toolUseContext?.agentId ?? getSessionId()
3656
- if (!hasHookForEvent(hookEvent, appState, sessionId)) {
3657
- return
3658
- }
3659
-
3660
- // Extract text content from the last assistant message so hooks can
3661
- // inspect the final response without reading the transcript file.
3662
- const lastAssistantMessage = messages
3663
- ? getLastAssistantMessage(messages)
3664
- : undefined
3665
- const lastAssistantText = lastAssistantMessage
3666
- ? extractTextContent(lastAssistantMessage.message.content, '\n').trim() ||
3667
- undefined
3668
- : undefined
3669
-
3670
- const hookInput: StopHookInput | SubagentStopHookInput = subagentId
3671
- ? {
3672
- ...createBaseHookInput(permissionMode),
3673
- hook_event_name: 'SubagentStop',
3674
- stop_hook_active: stopHookActive,
3675
- agent_id: subagentId,
3676
- agent_transcript_path: getAgentTranscriptPath(subagentId),
3677
- agent_type: agentType ?? '',
3678
- last_assistant_message: lastAssistantText,
3679
- }
3680
- : {
3681
- ...createBaseHookInput(permissionMode),
3682
- hook_event_name: 'Stop',
3683
- stop_hook_active: stopHookActive,
3684
- last_assistant_message: lastAssistantText,
3685
- }
3686
-
3687
- // Trust check is now centralized in executeHooks()
3688
- yield* executeHooks({
3689
- hookInput,
3690
- toolUseID: randomUUID(),
3691
- signal,
3692
- timeoutMs,
3693
- toolUseContext,
3694
- messages,
3695
- requestPrompt,
3696
- })
3697
- }
3698
-
3699
- /**
3700
- * Execute TeammateIdle hooks when a teammate is about to go idle.
3701
- * If a hook blocks (exit code 2), the teammate should continue working instead of going idle.
3702
- * @param teammateName The name of the teammate going idle
3703
- * @param teamName The team this teammate belongs to
3704
- * @param permissionMode Optional permission mode
3705
- * @param signal Optional AbortSignal to cancel hook execution
3706
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3707
- * @returns Async generator that yields progress messages and blocking errors
3708
- */
3709
- export async function* executeTeammateIdleHooks(
3710
- teammateName: string,
3711
- teamName: string,
3712
- permissionMode?: string,
3713
- signal?: AbortSignal,
3714
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3715
- ): AsyncGenerator<AggregatedHookResult> {
3716
- const hookInput: TeammateIdleHookInput = {
3717
- ...createBaseHookInput(permissionMode),
3718
- hook_event_name: 'TeammateIdle',
3719
- teammate_name: teammateName,
3720
- team_name: teamName,
3721
- }
3722
-
3723
- yield* executeHooks({
3724
- hookInput,
3725
- toolUseID: randomUUID(),
3726
- signal,
3727
- timeoutMs,
3728
- })
3729
- }
3730
-
3731
- /**
3732
- * Execute TaskCreated hooks when a task is being created.
3733
- * If a hook blocks (exit code 2), the task creation should be prevented and feedback returned.
3734
- * @param taskId The ID of the task being created
3735
- * @param taskSubject The subject/title of the task
3736
- * @param taskDescription Optional description of the task
3737
- * @param teammateName Optional name of the teammate creating the task
3738
- * @param teamName Optional team name
3739
- * @param permissionMode Optional permission mode
3740
- * @param signal Optional AbortSignal to cancel hook execution
3741
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3742
- * @param toolUseContext Optional ToolUseContext for resolving appState and sessionId
3743
- * @returns Async generator that yields progress messages and blocking errors
3744
- */
3745
- export async function* executeTaskCreatedHooks(
3746
- taskId: string,
3747
- taskSubject: string,
3748
- taskDescription?: string,
3749
- teammateName?: string,
3750
- teamName?: string,
3751
- permissionMode?: string,
3752
- signal?: AbortSignal,
3753
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3754
- toolUseContext?: ToolUseContext,
3755
- ): AsyncGenerator<AggregatedHookResult> {
3756
- const hookInput: TaskCreatedHookInput = {
3757
- ...createBaseHookInput(permissionMode),
3758
- hook_event_name: 'TaskCreated',
3759
- task_id: taskId,
3760
- task_subject: taskSubject,
3761
- task_description: taskDescription,
3762
- teammate_name: teammateName,
3763
- team_name: teamName,
3764
- }
3765
-
3766
- yield* executeHooks({
3767
- hookInput,
3768
- toolUseID: randomUUID(),
3769
- signal,
3770
- timeoutMs,
3771
- toolUseContext,
3772
- })
3773
- }
3774
-
3775
- /**
3776
- * Execute TaskCompleted hooks when a task is being marked as completed.
3777
- * If a hook blocks (exit code 2), the task completion should be prevented and feedback returned.
3778
- * @param taskId The ID of the task being completed
3779
- * @param taskSubject The subject/title of the task
3780
- * @param taskDescription Optional description of the task
3781
- * @param teammateName Optional name of the teammate completing the task
3782
- * @param teamName Optional team name
3783
- * @param permissionMode Optional permission mode
3784
- * @param signal Optional AbortSignal to cancel hook execution
3785
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3786
- * @param toolUseContext Optional ToolUseContext for resolving appState and sessionId
3787
- * @returns Async generator that yields progress messages and blocking errors
3788
- */
3789
- export async function* executeTaskCompletedHooks(
3790
- taskId: string,
3791
- taskSubject: string,
3792
- taskDescription?: string,
3793
- teammateName?: string,
3794
- teamName?: string,
3795
- permissionMode?: string,
3796
- signal?: AbortSignal,
3797
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3798
- toolUseContext?: ToolUseContext,
3799
- ): AsyncGenerator<AggregatedHookResult> {
3800
- const hookInput: TaskCompletedHookInput = {
3801
- ...createBaseHookInput(permissionMode),
3802
- hook_event_name: 'TaskCompleted',
3803
- task_id: taskId,
3804
- task_subject: taskSubject,
3805
- task_description: taskDescription,
3806
- teammate_name: teammateName,
3807
- team_name: teamName,
3808
- }
3809
-
3810
- yield* executeHooks({
3811
- hookInput,
3812
- toolUseID: randomUUID(),
3813
- signal,
3814
- timeoutMs,
3815
- toolUseContext,
3816
- })
3817
- }
3818
-
3819
- /**
3820
- * Execute start hooks if configured
3821
- * @param prompt The user prompt that will be passed to the tool
3822
- * @param permissionMode Permission mode from toolPermissionContext
3823
- * @param toolUseContext ToolUseContext for prompt-based hooks
3824
- * @returns Async generator that yields progress messages and hook results
3825
- */
3826
- export async function* executeUserPromptSubmitHooks(
3827
- prompt: string,
3828
- permissionMode: string,
3829
- toolUseContext: ToolUseContext,
3830
- requestPrompt?: (
3831
- sourceName: string,
3832
- toolInputSummary?: string | null,
3833
- ) => (request: PromptRequest) => Promise<PromptResponse>,
3834
- ): AsyncGenerator<AggregatedHookResult> {
3835
- const appState = toolUseContext.getAppState()
3836
- const sessionId = toolUseContext.agentId ?? getSessionId()
3837
- if (!hasHookForEvent('UserPromptSubmit', appState, sessionId)) {
3838
- return
3839
- }
3840
-
3841
- const hookInput: UserPromptSubmitHookInput = {
3842
- ...createBaseHookInput(permissionMode),
3843
- hook_event_name: 'UserPromptSubmit',
3844
- prompt,
3845
- }
3846
-
3847
- yield* executeHooks({
3848
- hookInput,
3849
- toolUseID: randomUUID(),
3850
- signal: toolUseContext.abortController.signal,
3851
- timeoutMs: TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3852
- toolUseContext,
3853
- requestPrompt,
3854
- })
3855
- }
3856
-
3857
- /**
3858
- * Execute session start hooks if configured
3859
- * @param source The source of the session start (startup, resume, clear)
3860
- * @param sessionId Optional The session id to use as hook input
3861
- * @param agentType Optional The agent type (from --agent flag) running this session
3862
- * @param model Optional The model being used for this session
3863
- * @param signal Optional AbortSignal to cancel hook execution
3864
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3865
- * @returns Async generator that yields progress messages and hook results
3866
- */
3867
- export async function* executeSessionStartHooks(
3868
- source: 'startup' | 'resume' | 'clear' | 'compact',
3869
- sessionId?: string,
3870
- agentType?: string,
3871
- model?: string,
3872
- signal?: AbortSignal,
3873
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3874
- forceSyncExecution?: boolean,
3875
- ): AsyncGenerator<AggregatedHookResult> {
3876
- const hookInput: SessionStartHookInput = {
3877
- ...createBaseHookInput(undefined, sessionId),
3878
- hook_event_name: 'SessionStart',
3879
- source,
3880
- agent_type: agentType,
3881
- model,
3882
- }
3883
-
3884
- yield* executeHooks({
3885
- hookInput,
3886
- toolUseID: randomUUID(),
3887
- matchQuery: source,
3888
- signal,
3889
- timeoutMs,
3890
- forceSyncExecution,
3891
- })
3892
- }
3893
-
3894
- /**
3895
- * Execute setup hooks if configured
3896
- * @param trigger The trigger type ('init' or 'maintenance')
3897
- * @param signal Optional AbortSignal to cancel hook execution
3898
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3899
- * @param forceSyncExecution If true, async hooks will not be backgrounded
3900
- * @returns Async generator that yields progress messages and hook results
3901
- */
3902
- export async function* executeSetupHooks(
3903
- trigger: 'init' | 'maintenance',
3904
- signal?: AbortSignal,
3905
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3906
- forceSyncExecution?: boolean,
3907
- ): AsyncGenerator<AggregatedHookResult> {
3908
- const hookInput: SetupHookInput = {
3909
- ...createBaseHookInput(undefined),
3910
- hook_event_name: 'Setup',
3911
- trigger,
3912
- }
3913
-
3914
- yield* executeHooks({
3915
- hookInput,
3916
- toolUseID: randomUUID(),
3917
- matchQuery: trigger,
3918
- signal,
3919
- timeoutMs,
3920
- forceSyncExecution,
3921
- })
3922
- }
3923
-
3924
- /**
3925
- * Execute subagent start hooks if configured
3926
- * @param agentId The unique identifier for the subagent
3927
- * @param agentType The type/name of the subagent being started
3928
- * @param signal Optional AbortSignal to cancel hook execution
3929
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3930
- * @returns Async generator that yields progress messages and hook results
3931
- */
3932
- export async function* executeSubagentStartHooks(
3933
- agentId: string,
3934
- agentType: string,
3935
- signal?: AbortSignal,
3936
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3937
- ): AsyncGenerator<AggregatedHookResult> {
3938
- const hookInput: SubagentStartHookInput = {
3939
- ...createBaseHookInput(undefined),
3940
- hook_event_name: 'SubagentStart',
3941
- agent_id: agentId,
3942
- agent_type: agentType,
3943
- }
3944
-
3945
- yield* executeHooks({
3946
- hookInput,
3947
- toolUseID: randomUUID(),
3948
- matchQuery: agentType,
3949
- signal,
3950
- timeoutMs,
3951
- })
3952
- }
3953
-
3954
- /**
3955
- * Execute pre-compact hooks if configured
3956
- * @param compactData The compact data to pass to hooks
3957
- * @param signal Optional AbortSignal to cancel hook execution
3958
- * @param timeoutMs Optional timeout in milliseconds for hook execution
3959
- * @returns Object with optional newCustomInstructions and userDisplayMessage
3960
- */
3961
- export async function executePreCompactHooks(
3962
- compactData: {
3963
- trigger: 'manual' | 'auto'
3964
- customInstructions: string | null
3965
- },
3966
- signal?: AbortSignal,
3967
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
3968
- ): Promise<{
3969
- newCustomInstructions?: string
3970
- userDisplayMessage?: string
3971
- }> {
3972
- const hookInput: PreCompactHookInput = {
3973
- ...createBaseHookInput(undefined),
3974
- hook_event_name: 'PreCompact',
3975
- trigger: compactData.trigger,
3976
- custom_instructions: compactData.customInstructions,
3977
- }
3978
-
3979
- const results = await executeHooksOutsideREPL({
3980
- hookInput,
3981
- matchQuery: compactData.trigger,
3982
- signal,
3983
- timeoutMs,
3984
- })
3985
-
3986
- if (results.length === 0) {
3987
- return {}
3988
- }
3989
-
3990
- // Extract custom instructions from successful hooks with non-empty output
3991
- const successfulOutputs = results
3992
- .filter(result => result.succeeded && result.output.trim().length > 0)
3993
- .map(result => result.output.trim())
3994
-
3995
- // Build user display messages with command info
3996
- const displayMessages: string[] = []
3997
- for (const result of results) {
3998
- if (result.succeeded) {
3999
- if (result.output.trim()) {
4000
- displayMessages.push(
4001
- `PreCompact [${result.command}] completed successfully: ${result.output.trim()}`,
4002
- )
4003
- } else {
4004
- displayMessages.push(
4005
- `PreCompact [${result.command}] completed successfully`,
4006
- )
4007
- }
4008
- } else {
4009
- if (result.output.trim()) {
4010
- displayMessages.push(
4011
- `PreCompact [${result.command}] failed: ${result.output.trim()}`,
4012
- )
4013
- } else {
4014
- displayMessages.push(`PreCompact [${result.command}] failed`)
4015
- }
4016
- }
4017
- }
4018
-
4019
- return {
4020
- newCustomInstructions:
4021
- successfulOutputs.length > 0 ? successfulOutputs.join('\n\n') : undefined,
4022
- userDisplayMessage:
4023
- displayMessages.length > 0 ? displayMessages.join('\n') : undefined,
4024
- }
4025
- }
4026
-
4027
- /**
4028
- * Execute post-compact hooks if configured
4029
- * @param compactData The compact data to pass to hooks, including the summary
4030
- * @param signal Optional AbortSignal to cancel hook execution
4031
- * @param timeoutMs Optional timeout in milliseconds for hook execution
4032
- * @returns Object with optional userDisplayMessage
4033
- */
4034
- export async function executePostCompactHooks(
4035
- compactData: {
4036
- trigger: 'manual' | 'auto'
4037
- compactSummary: string
4038
- },
4039
- signal?: AbortSignal,
4040
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4041
- ): Promise<{
4042
- userDisplayMessage?: string
4043
- }> {
4044
- const hookInput: PostCompactHookInput = {
4045
- ...createBaseHookInput(undefined),
4046
- hook_event_name: 'PostCompact',
4047
- trigger: compactData.trigger,
4048
- compact_summary: compactData.compactSummary,
4049
- }
4050
-
4051
- const results = await executeHooksOutsideREPL({
4052
- hookInput,
4053
- matchQuery: compactData.trigger,
4054
- signal,
4055
- timeoutMs,
4056
- })
4057
-
4058
- if (results.length === 0) {
4059
- return {}
4060
- }
4061
-
4062
- const displayMessages: string[] = []
4063
- for (const result of results) {
4064
- if (result.succeeded) {
4065
- if (result.output.trim()) {
4066
- displayMessages.push(
4067
- `PostCompact [${result.command}] completed successfully: ${result.output.trim()}`,
4068
- )
4069
- } else {
4070
- displayMessages.push(
4071
- `PostCompact [${result.command}] completed successfully`,
4072
- )
4073
- }
4074
- } else {
4075
- if (result.output.trim()) {
4076
- displayMessages.push(
4077
- `PostCompact [${result.command}] failed: ${result.output.trim()}`,
4078
- )
4079
- } else {
4080
- displayMessages.push(`PostCompact [${result.command}] failed`)
4081
- }
4082
- }
4083
- }
4084
-
4085
- return {
4086
- userDisplayMessage:
4087
- displayMessages.length > 0 ? displayMessages.join('\n') : undefined,
4088
- }
4089
- }
4090
-
4091
- /**
4092
- * Execute session end hooks if configured
4093
- * @param reason The reason for ending the session
4094
- * @param options Optional parameters including app state functions and signal
4095
- * @returns Promise that resolves when all hooks complete
4096
- */
4097
- export async function executeSessionEndHooks(
4098
- reason: ExitReason,
4099
- options?: {
4100
- getAppState?: () => AppState
4101
- setAppState?: (updater: (prev: AppState) => AppState) => void
4102
- signal?: AbortSignal
4103
- timeoutMs?: number
4104
- },
4105
- ): Promise<void> {
4106
- const {
4107
- getAppState,
4108
- setAppState,
4109
- signal,
4110
- timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4111
- } = options || {}
4112
-
4113
- const hookInput: SessionEndHookInput = {
4114
- ...createBaseHookInput(undefined),
4115
- hook_event_name: 'SessionEnd',
4116
- reason,
4117
- }
4118
-
4119
- const results = await executeHooksOutsideREPL({
4120
- getAppState,
4121
- hookInput,
4122
- matchQuery: reason,
4123
- signal,
4124
- timeoutMs,
4125
- })
4126
-
4127
- // During shutdown, Ink is unmounted so we can write directly to stderr
4128
- for (const result of results) {
4129
- if (!result.succeeded && result.output) {
4130
- process.stderr.write(
4131
- `SessionEnd hook [${result.command}] failed: ${result.output}\n`,
4132
- )
4133
- }
4134
- }
4135
-
4136
- // Clear session hooks after execution
4137
- if (setAppState) {
4138
- const sessionId = getSessionId()
4139
- clearSessionHooks(setAppState, sessionId)
4140
- }
4141
- }
4142
-
4143
- /**
4144
- * Execute permission request hooks if configured
4145
- * These hooks are called when a permission dialog would be displayed to the user.
4146
- * Hooks can approve or deny the permission request programmatically.
4147
- * @param toolName The name of the tool requesting permission
4148
- * @param toolUseID The ID of the tool use
4149
- * @param toolInput The input that would be passed to the tool
4150
- * @param toolUseContext ToolUseContext for the request
4151
- * @param permissionMode Optional permission mode from toolPermissionContext
4152
- * @param permissionSuggestions Optional permission suggestions (the "always allow" options)
4153
- * @param signal Optional AbortSignal to cancel hook execution
4154
- * @param timeoutMs Optional timeout in milliseconds for hook execution
4155
- * @returns Async generator that yields progress messages and returns aggregated result
4156
- */
4157
- export async function* executePermissionRequestHooks<ToolInput>(
4158
- toolName: string,
4159
- toolUseID: string,
4160
- toolInput: ToolInput,
4161
- toolUseContext: ToolUseContext,
4162
- permissionMode?: string,
4163
- permissionSuggestions?: PermissionUpdate[],
4164
- signal?: AbortSignal,
4165
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4166
- requestPrompt?: (
4167
- sourceName: string,
4168
- toolInputSummary?: string | null,
4169
- ) => (request: PromptRequest) => Promise<PromptResponse>,
4170
- toolInputSummary?: string | null,
4171
- ): AsyncGenerator<AggregatedHookResult> {
4172
- logForDebugging(`executePermissionRequestHooks called for tool: ${toolName}`)
4173
-
4174
- const hookInput: PermissionRequestHookInput = {
4175
- ...createBaseHookInput(permissionMode, undefined, toolUseContext),
4176
- hook_event_name: 'PermissionRequest',
4177
- tool_name: toolName,
4178
- tool_input: toolInput,
4179
- permission_suggestions: permissionSuggestions,
4180
- }
4181
-
4182
- yield* executeHooks({
4183
- hookInput,
4184
- toolUseID,
4185
- matchQuery: toolName,
4186
- signal,
4187
- timeoutMs,
4188
- toolUseContext,
4189
- requestPrompt,
4190
- toolInputSummary,
4191
- })
4192
- }
4193
-
4194
- export type ConfigChangeSource =
4195
- | 'user_settings'
4196
- | 'project_settings'
4197
- | 'local_settings'
4198
- | 'policy_settings'
4199
- | 'skills'
4200
-
4201
- /**
4202
- * Execute config change hooks when configuration files change during a session.
4203
- * Fired by file watchers when settings, skills, or commands change on disk.
4204
- * Enables enterprise admins to audit/log configuration changes for security.
4205
- *
4206
- * Policy settings are enterprise-managed and must never be blockable by hooks.
4207
- * Hooks still fire (for audit logging) but blocking results are ignored — callers
4208
- * will always see an empty result for policy sources.
4209
- *
4210
- * @param source The type of config that changed
4211
- * @param filePath Optional path to the changed file
4212
- * @param timeoutMs Optional timeout in milliseconds for hook execution
4213
- */
4214
- export async function executeConfigChangeHooks(
4215
- source: ConfigChangeSource,
4216
- filePath?: string,
4217
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4218
- ): Promise<HookOutsideReplResult[]> {
4219
- const hookInput: ConfigChangeHookInput = {
4220
- ...createBaseHookInput(undefined),
4221
- hook_event_name: 'ConfigChange',
4222
- source,
4223
- file_path: filePath,
4224
- }
4225
-
4226
- const results = await executeHooksOutsideREPL({
4227
- hookInput,
4228
- timeoutMs,
4229
- matchQuery: source,
4230
- })
4231
-
4232
- // Policy settings are enterprise-managed — hooks fire for audit logging
4233
- // but must never block policy changes from being applied
4234
- if (source === 'policy_settings') {
4235
- return results.map(r => ({ ...r, blocked: false }))
4236
- }
4237
-
4238
- return results
4239
- }
4240
-
4241
- async function executeEnvHooks(
4242
- hookInput: HookInput,
4243
- timeoutMs: number,
4244
- ): Promise<{
4245
- results: HookOutsideReplResult[]
4246
- watchPaths: string[]
4247
- systemMessages: string[]
4248
- }> {
4249
- const results = await executeHooksOutsideREPL({ hookInput, timeoutMs })
4250
- if (results.length > 0) {
4251
- invalidateSessionEnvCache()
4252
- }
4253
- const watchPaths = results.flatMap(r => r.watchPaths ?? [])
4254
- const systemMessages = results
4255
- .map(r => r.systemMessage)
4256
- .filter((m): m is string => !!m)
4257
- return { results, watchPaths, systemMessages }
4258
- }
4259
-
4260
- export function executeCwdChangedHooks(
4261
- oldCwd: string,
4262
- newCwd: string,
4263
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4264
- ): Promise<{
4265
- results: HookOutsideReplResult[]
4266
- watchPaths: string[]
4267
- systemMessages: string[]
4268
- }> {
4269
- const hookInput: CwdChangedHookInput = {
4270
- ...createBaseHookInput(undefined),
4271
- hook_event_name: 'CwdChanged',
4272
- old_cwd: oldCwd,
4273
- new_cwd: newCwd,
4274
- }
4275
- return executeEnvHooks(hookInput, timeoutMs)
4276
- }
4277
-
4278
- export function executeFileChangedHooks(
4279
- filePath: string,
4280
- event: 'change' | 'add' | 'unlink',
4281
- timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4282
- ): Promise<{
4283
- results: HookOutsideReplResult[]
4284
- watchPaths: string[]
4285
- systemMessages: string[]
4286
- }> {
4287
- const hookInput: FileChangedHookInput = {
4288
- ...createBaseHookInput(undefined),
4289
- hook_event_name: 'FileChanged',
4290
- file_path: filePath,
4291
- event,
4292
- }
4293
- return executeEnvHooks(hookInput, timeoutMs)
4294
- }
4295
-
4296
- export type InstructionsLoadReason =
4297
- | 'session_start'
4298
- | 'nested_traversal'
4299
- | 'path_glob_match'
4300
- | 'include'
4301
- | 'compact'
4302
-
4303
- export type InstructionsMemoryType = 'User' | 'Project' | 'Local' | 'Managed'
4304
-
4305
- /**
4306
- * Check if InstructionsLoaded hooks are configured (without executing them).
4307
- * Callers should check this before invoking executeInstructionsLoadedHooks to avoid
4308
- * building hook inputs for every instruction file when no hook is configured.
4309
- *
4310
- * Checks both settings-file hooks (getHooksConfigFromSnapshot) and registered
4311
- * hooks (plugin hooks + SDK callback hooks via registerHookCallbacks). Session-
4312
- * derived hooks (structured output enforcement etc.) are internal and not checked.
4313
- */
4314
- export function hasInstructionsLoadedHook(): boolean {
4315
- const snapshotHooks = getHooksConfigFromSnapshot()?.['InstructionsLoaded']
4316
- if (snapshotHooks && snapshotHooks.length > 0) return true
4317
- const registeredHooks = getRegisteredHooks()?.['InstructionsLoaded']
4318
- if (registeredHooks && registeredHooks.length > 0) return true
4319
- return false
4320
- }
4321
-
4322
- /**
4323
- * Execute InstructionsLoaded hooks when an instruction file (CLAUDE.md or
4324
- * .claude/rules/*.md) is loaded into context. Fire-and-forget — this hook is
4325
- * for observability/audit only and does not support blocking.
4326
- *
4327
- * Dispatch sites:
4328
- * - Eager load at session start (getMemoryFiles in claudemd.ts)
4329
- * - Eager reload after compaction (getMemoryFiles cache cleared by
4330
- * runPostCompactCleanup; next call reports load_reason: 'compact')
4331
- * - Lazy load when Claude touches a file that triggers nested CLAUDE.md or
4332
- * conditional rules with paths: frontmatter (memoryFilesToAttachments in
4333
- * attachments.ts)
4334
- */
4335
- export async function executeInstructionsLoadedHooks(
4336
- filePath: string,
4337
- memoryType: InstructionsMemoryType,
4338
- loadReason: InstructionsLoadReason,
4339
- options?: {
4340
- globs?: string[]
4341
- triggerFilePath?: string
4342
- parentFilePath?: string
4343
- timeoutMs?: number
4344
- },
4345
- ): Promise<void> {
4346
- const {
4347
- globs,
4348
- triggerFilePath,
4349
- parentFilePath,
4350
- timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4351
- } = options ?? {}
4352
-
4353
- const hookInput: InstructionsLoadedHookInput = {
4354
- ...createBaseHookInput(undefined),
4355
- hook_event_name: 'InstructionsLoaded',
4356
- file_path: filePath,
4357
- memory_type: memoryType,
4358
- load_reason: loadReason,
4359
- globs,
4360
- trigger_file_path: triggerFilePath,
4361
- parent_file_path: parentFilePath,
4362
- }
4363
-
4364
- await executeHooksOutsideREPL({
4365
- hookInput,
4366
- timeoutMs,
4367
- matchQuery: loadReason,
4368
- })
4369
- }
4370
-
4371
- /** Result of an elicitation hook execution (non-REPL path). */
4372
- export type ElicitationHookResult = {
4373
- elicitationResponse?: ElicitationResponse
4374
- blockingError?: HookBlockingError
4375
- }
4376
-
4377
- /** Result of an elicitation-result hook execution (non-REPL path). */
4378
- export type ElicitationResultHookResult = {
4379
- elicitationResultResponse?: ElicitationResponse
4380
- blockingError?: HookBlockingError
4381
- }
4382
-
4383
- /**
4384
- * Parse elicitation-specific fields from a HookOutsideReplResult.
4385
- * Mirrors the relevant branches of processHookJSONOutput for Elicitation
4386
- * and ElicitationResult hook events.
4387
- */
4388
- function parseElicitationHookOutput(
4389
- result: HookOutsideReplResult,
4390
- expectedEventName: 'Elicitation' | 'ElicitationResult',
4391
- ): {
4392
- response?: ElicitationResponse
4393
- blockingError?: HookBlockingError
4394
- } {
4395
- // Exit code 2 = blocking (same as executeHooks path)
4396
- if (result.blocked && !result.succeeded) {
4397
- return {
4398
- blockingError: {
4399
- blockingError: result.output || `Elicitation blocked by hook`,
4400
- command: result.command,
4401
- },
4402
- }
4403
- }
4404
-
4405
- if (!result.output.trim()) {
4406
- return {}
4407
- }
4408
-
4409
- // Try to parse JSON output for structured elicitation response
4410
- const trimmed = result.output.trim()
4411
- if (!trimmed.startsWith('{')) {
4412
- return {}
4413
- }
4414
-
4415
- try {
4416
- const parsed = hookJSONOutputSchema().parse(JSON.parse(trimmed))
4417
- if (isAsyncHookJSONOutput(parsed)) {
4418
- return {}
4419
- }
4420
- if (!isSyncHookJSONOutput(parsed)) {
4421
- return {}
4422
- }
4423
-
4424
- // Check for top-level decision: 'block' (exit code 0 + JSON block)
4425
- if (parsed.decision === 'block' || result.blocked) {
4426
- return {
4427
- blockingError: {
4428
- blockingError: parsed.reason || 'Elicitation blocked by hook',
4429
- command: result.command,
4430
- },
4431
- }
4432
- }
4433
-
4434
- const specific = parsed.hookSpecificOutput
4435
- if (!specific || specific.hookEventName !== expectedEventName) {
4436
- return {}
4437
- }
4438
-
4439
- if (!specific.action) {
4440
- return {}
4441
- }
4442
-
4443
- const response: ElicitationResponse = {
4444
- action: specific.action,
4445
- content: specific.content as ElicitationResponse['content'] | undefined,
4446
- }
4447
-
4448
- const out: {
4449
- response?: ElicitationResponse
4450
- blockingError?: HookBlockingError
4451
- } = { response }
4452
-
4453
- if (specific.action === 'decline') {
4454
- out.blockingError = {
4455
- blockingError:
4456
- parsed.reason ||
4457
- (expectedEventName === 'Elicitation'
4458
- ? 'Elicitation denied by hook'
4459
- : 'Elicitation result blocked by hook'),
4460
- command: result.command,
4461
- }
4462
- }
4463
-
4464
- return out
4465
- } catch {
4466
- return {}
4467
- }
4468
- }
4469
-
4470
- export async function executeElicitationHooks({
4471
- serverName,
4472
- message,
4473
- requestedSchema,
4474
- permissionMode,
4475
- signal,
4476
- timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4477
- mode,
4478
- url,
4479
- elicitationId,
4480
- }: {
4481
- serverName: string
4482
- message: string
4483
- requestedSchema?: Record<string, unknown>
4484
- permissionMode?: string
4485
- signal?: AbortSignal
4486
- timeoutMs?: number
4487
- mode?: 'form' | 'url'
4488
- url?: string
4489
- elicitationId?: string
4490
- }): Promise<ElicitationHookResult> {
4491
- const hookInput: ElicitationHookInput = {
4492
- ...createBaseHookInput(permissionMode),
4493
- hook_event_name: 'Elicitation',
4494
- mcp_server_name: serverName,
4495
- message,
4496
- mode,
4497
- url,
4498
- elicitation_id: elicitationId,
4499
- requested_schema: requestedSchema,
4500
- }
4501
-
4502
- const results = await executeHooksOutsideREPL({
4503
- hookInput,
4504
- matchQuery: serverName,
4505
- signal,
4506
- timeoutMs,
4507
- })
4508
-
4509
- let elicitationResponse: ElicitationResponse | undefined
4510
- let blockingError: HookBlockingError | undefined
4511
-
4512
- for (const result of results) {
4513
- const parsed = parseElicitationHookOutput(result, 'Elicitation')
4514
- if (parsed.blockingError) {
4515
- blockingError = parsed.blockingError
4516
- }
4517
- if (parsed.response) {
4518
- elicitationResponse = parsed.response
4519
- }
4520
- }
4521
-
4522
- return { elicitationResponse, blockingError }
4523
- }
4524
-
4525
- export async function executeElicitationResultHooks({
4526
- serverName,
4527
- action,
4528
- content,
4529
- permissionMode,
4530
- signal,
4531
- timeoutMs = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4532
- mode,
4533
- elicitationId,
4534
- }: {
4535
- serverName: string
4536
- action: 'accept' | 'decline' | 'cancel'
4537
- content?: Record<string, unknown>
4538
- permissionMode?: string
4539
- signal?: AbortSignal
4540
- timeoutMs?: number
4541
- mode?: 'form' | 'url'
4542
- elicitationId?: string
4543
- }): Promise<ElicitationResultHookResult> {
4544
- const hookInput: ElicitationResultHookInput = {
4545
- ...createBaseHookInput(permissionMode),
4546
- hook_event_name: 'ElicitationResult',
4547
- mcp_server_name: serverName,
4548
- elicitation_id: elicitationId,
4549
- mode,
4550
- action,
4551
- content,
4552
- }
4553
-
4554
- const results = await executeHooksOutsideREPL({
4555
- hookInput,
4556
- matchQuery: serverName,
4557
- signal,
4558
- timeoutMs,
4559
- })
4560
-
4561
- let elicitationResultResponse: ElicitationResponse | undefined
4562
- let blockingError: HookBlockingError | undefined
4563
-
4564
- for (const result of results) {
4565
- const parsed = parseElicitationHookOutput(result, 'ElicitationResult')
4566
- if (parsed.blockingError) {
4567
- blockingError = parsed.blockingError
4568
- }
4569
- if (parsed.response) {
4570
- elicitationResultResponse = parsed.response
4571
- }
4572
- }
4573
-
4574
- return { elicitationResultResponse, blockingError }
4575
- }
4576
-
4577
- /**
4578
- * Execute status line command if configured
4579
- * @param statusLineInput The structured status input that will be converted to JSON
4580
- * @param signal Optional AbortSignal to cancel hook execution
4581
- * @param timeoutMs Optional timeout in milliseconds for hook execution
4582
- * @returns The status line text to display, or undefined if no command configured
4583
- */
4584
- export async function executeStatusLineCommand(
4585
- statusLineInput: StatusLineCommandInput,
4586
- signal?: AbortSignal,
4587
- timeoutMs: number = 5000, // Short timeout for status line
4588
- logResult: boolean = false,
4589
- ): Promise<string | undefined> {
4590
- // Check if all hooks (including statusLine) are disabled by managed settings
4591
- if (shouldDisableAllHooksIncludingManaged()) {
4592
- return undefined
4593
- }
4594
-
4595
- // SECURITY: ALL hooks require workspace trust in interactive mode
4596
- // This centralized check prevents RCE vulnerabilities for all current and future hooks
4597
- if (shouldSkipHookDueToTrust()) {
4598
- logForDebugging(
4599
- `Skipping StatusLine command execution - workspace trust not accepted`,
4600
- )
4601
- return undefined
4602
- }
4603
-
4604
- // When disableAllHooks is set in non-managed settings, only managed statusLine runs
4605
- // (non-managed settings cannot disable managed commands, but non-managed commands are disabled)
4606
- let statusLine
4607
- if (shouldAllowManagedHooksOnly()) {
4608
- statusLine = getSettingsForSource('policySettings')?.statusLine
4609
- } else {
4610
- statusLine = getSettings_DEPRECATED()?.statusLine
4611
- }
4612
-
4613
- if (!statusLine || statusLine.type !== 'command') {
4614
- return undefined
4615
- }
4616
-
4617
- // Use provided signal or create a default one
4618
- const abortSignal = signal || AbortSignal.timeout(timeoutMs)
4619
-
4620
- try {
4621
- // Convert status input to JSON
4622
- const jsonInput = jsonStringify(statusLineInput)
4623
-
4624
- const result = await execCommandHook(
4625
- statusLine,
4626
- 'StatusLine',
4627
- 'statusLine',
4628
- jsonInput,
4629
- abortSignal,
4630
- randomUUID(),
4631
- )
4632
-
4633
- if (result.aborted) {
4634
- return undefined
4635
- }
4636
-
4637
- // For successful hooks (exit code 0), use stdout
4638
- if (result.status === 0) {
4639
- // Trim and split output into lines, then join with newlines
4640
- const output = result.stdout
4641
- .trim()
4642
- .split('\n')
4643
- .flatMap(line => line.trim() || [])
4644
- .join('\n')
4645
-
4646
- if (output) {
4647
- if (logResult) {
4648
- logForDebugging(
4649
- `StatusLine [${statusLine.command}] completed with status ${result.status}`,
4650
- )
4651
- }
4652
- return output
4653
- }
4654
- } else if (logResult) {
4655
- logForDebugging(
4656
- `StatusLine [${statusLine.command}] completed with status ${result.status}`,
4657
- { level: 'warn' },
4658
- )
4659
- }
4660
-
4661
- return undefined
4662
- } catch (error) {
4663
- logForDebugging(`Status hook failed: ${error}`, { level: 'error' })
4664
- return undefined
4665
- }
4666
- }
4667
-
4668
- /**
4669
- * Execute file suggestion command if configured
4670
- * @param fileSuggestionInput The structured input that will be converted to JSON
4671
- * @param signal Optional AbortSignal to cancel hook execution
4672
- * @param timeoutMs Optional timeout in milliseconds for hook execution
4673
- * @returns Array of file paths, or empty array if no command configured
4674
- */
4675
- export async function executeFileSuggestionCommand(
4676
- fileSuggestionInput: FileSuggestionCommandInput,
4677
- signal?: AbortSignal,
4678
- timeoutMs: number = 5000, // Short timeout for typeahead suggestions
4679
- ): Promise<string[]> {
4680
- // Check if all hooks are disabled by managed settings
4681
- if (shouldDisableAllHooksIncludingManaged()) {
4682
- return []
4683
- }
4684
-
4685
- // SECURITY: ALL hooks require workspace trust in interactive mode
4686
- // This centralized check prevents RCE vulnerabilities for all current and future hooks
4687
- if (shouldSkipHookDueToTrust()) {
4688
- logForDebugging(
4689
- `Skipping FileSuggestion command execution - workspace trust not accepted`,
4690
- )
4691
- return []
4692
- }
4693
-
4694
- // When disableAllHooks is set in non-managed settings, only managed fileSuggestion runs
4695
- // (non-managed settings cannot disable managed commands, but non-managed commands are disabled)
4696
- let fileSuggestion
4697
- if (shouldAllowManagedHooksOnly()) {
4698
- fileSuggestion = getSettingsForSource('policySettings')?.fileSuggestion
4699
- } else {
4700
- fileSuggestion = getSettings_DEPRECATED()?.fileSuggestion
4701
- }
4702
-
4703
- if (!fileSuggestion || fileSuggestion.type !== 'command') {
4704
- return []
4705
- }
4706
-
4707
- // Use provided signal or create a default one
4708
- const abortSignal = signal || AbortSignal.timeout(timeoutMs)
4709
-
4710
- try {
4711
- const jsonInput = jsonStringify(fileSuggestionInput)
4712
-
4713
- const hook = { type: 'command' as const, command: fileSuggestion.command }
4714
-
4715
- const result = await execCommandHook(
4716
- hook,
4717
- 'FileSuggestion',
4718
- 'FileSuggestion',
4719
- jsonInput,
4720
- abortSignal,
4721
- randomUUID(),
4722
- )
4723
-
4724
- if (result.aborted || result.status !== 0) {
4725
- return []
4726
- }
4727
-
4728
- return result.stdout
4729
- .split('\n')
4730
- .map(line => line.trim())
4731
- .filter(Boolean)
4732
- } catch (error) {
4733
- logForDebugging(`File suggestion helper failed: ${error}`, {
4734
- level: 'error',
4735
- })
4736
- return []
4737
- }
4738
- }
4739
-
4740
- async function executeFunctionHook({
4741
- hook,
4742
- messages,
4743
- hookName,
4744
- toolUseID,
4745
- hookEvent,
4746
- timeoutMs,
4747
- signal,
4748
- }: {
4749
- hook: FunctionHook
4750
- messages: Message[]
4751
- hookName: string
4752
- toolUseID: string
4753
- hookEvent: HookEvent
4754
- timeoutMs: number
4755
- signal?: AbortSignal
4756
- }): Promise<HookResult> {
4757
- const callbackTimeoutMs = hook.timeout ?? timeoutMs
4758
- const { signal: abortSignal, cleanup } = createCombinedAbortSignal(signal, {
4759
- timeoutMs: callbackTimeoutMs,
4760
- })
4761
-
4762
- try {
4763
- // Check if already aborted
4764
- if (abortSignal.aborted) {
4765
- cleanup()
4766
- return {
4767
- outcome: 'cancelled',
4768
- hook,
4769
- }
4770
- }
4771
-
4772
- // Execute callback with abort signal
4773
- const passed = await new Promise<boolean>((resolve, reject) => {
4774
- // Handle abort signal
4775
- const onAbort = () => reject(new Error('Function hook cancelled'))
4776
- abortSignal.addEventListener('abort', onAbort)
4777
-
4778
- // Execute callback
4779
- Promise.resolve(hook.callback(messages, abortSignal))
4780
- .then(result => {
4781
- abortSignal.removeEventListener('abort', onAbort)
4782
- resolve(result)
4783
- })
4784
- .catch(error => {
4785
- abortSignal.removeEventListener('abort', onAbort)
4786
- reject(error)
4787
- })
4788
- })
4789
-
4790
- cleanup()
4791
-
4792
- if (passed) {
4793
- return {
4794
- outcome: 'success',
4795
- hook,
4796
- }
4797
- }
4798
- return {
4799
- blockingError: {
4800
- blockingError: hook.errorMessage,
4801
- command: 'function',
4802
- },
4803
- outcome: 'blocking',
4804
- hook,
4805
- }
4806
- } catch (error) {
4807
- cleanup()
4808
-
4809
- // Handle cancellation
4810
- if (
4811
- error instanceof Error &&
4812
- (error.message === 'Function hook cancelled' ||
4813
- error.name === 'AbortError')
4814
- ) {
4815
- return {
4816
- outcome: 'cancelled',
4817
- hook,
4818
- }
4819
- }
4820
-
4821
- // Log for monitoring
4822
- logError(error)
4823
- return {
4824
- message: createAttachmentMessage({
4825
- type: 'hook_error_during_execution',
4826
- hookName,
4827
- toolUseID,
4828
- hookEvent,
4829
- content:
4830
- error instanceof Error
4831
- ? error.message
4832
- : 'Function hook execution error',
4833
- }),
4834
- outcome: 'non_blocking_error',
4835
- hook,
4836
- }
4837
- }
4838
- }
4839
-
4840
- async function executeHookCallback({
4841
- toolUseID,
4842
- hook,
4843
- hookEvent,
4844
- hookInput,
4845
- signal,
4846
- hookIndex,
4847
- toolUseContext,
4848
- }: {
4849
- toolUseID: string
4850
- hook: HookCallback
4851
- hookEvent: HookEvent
4852
- hookInput: HookInput
4853
- signal: AbortSignal
4854
- hookIndex?: number
4855
- toolUseContext?: ToolUseContext
4856
- }): Promise<HookResult> {
4857
- // Create context for callbacks that need state access
4858
- const context = toolUseContext
4859
- ? {
4860
- getAppState: toolUseContext.getAppState,
4861
- updateAttributionState: toolUseContext.updateAttributionState,
4862
- }
4863
- : undefined
4864
- const json = await hook.callback(
4865
- hookInput,
4866
- toolUseID,
4867
- signal,
4868
- hookIndex,
4869
- context,
4870
- )
4871
- if (isAsyncHookJSONOutput(json)) {
4872
- return {
4873
- outcome: 'success',
4874
- hook,
4875
- }
4876
- }
4877
-
4878
- const processed = processHookJSONOutput({
4879
- json,
4880
- command: 'callback',
4881
- // TODO: If the hook came from a plugin, use the full path to the plugin for easier debugging
4882
- hookName: `${hookEvent}:Callback`,
4883
- toolUseID,
4884
- hookEvent,
4885
- expectedHookEvent: hookEvent,
4886
- // Callbacks don't have stdout/stderr/exitCode
4887
- stdout: undefined,
4888
- stderr: undefined,
4889
- exitCode: undefined,
4890
- })
4891
- return {
4892
- ...processed,
4893
- outcome: 'success',
4894
- hook,
4895
- }
4896
- }
4897
-
4898
- /**
4899
- * Check if WorktreeCreate hooks are configured (without executing them).
4900
- *
4901
- * Checks both settings-file hooks (getHooksConfigFromSnapshot) and registered
4902
- * hooks (plugin hooks + SDK callback hooks via registerHookCallbacks).
4903
- *
4904
- * Must mirror the managedOnly filtering in getHooksConfig() — when
4905
- * shouldAllowManagedHooksOnly() is true, plugin hooks (pluginRoot set) are
4906
- * skipped at execution, so we must also skip them here. Otherwise this returns
4907
- * true but executeWorktreeCreateHook() finds no matching hooks and throws,
4908
- * blocking the git-worktree fallback.
4909
- */
4910
- export function hasWorktreeCreateHook(): boolean {
4911
- const snapshotHooks = getHooksConfigFromSnapshot()?.['WorktreeCreate']
4912
- if (snapshotHooks && snapshotHooks.length > 0) return true
4913
- const registeredHooks = getRegisteredHooks()?.['WorktreeCreate']
4914
- if (!registeredHooks || registeredHooks.length === 0) return false
4915
- // Mirror getHooksConfig(): skip plugin hooks in managed-only mode
4916
- const managedOnly = shouldAllowManagedHooksOnly()
4917
- return registeredHooks.some(
4918
- matcher => !(managedOnly && 'pluginRoot' in matcher),
4919
- )
4920
- }
4921
-
4922
- /**
4923
- * Execute WorktreeCreate hooks.
4924
- * Returns the worktree path from hook stdout.
4925
- * Throws if hooks fail or produce no output.
4926
- * Callers should check hasWorktreeCreateHook() before calling this.
4927
- */
4928
- export async function executeWorktreeCreateHook(
4929
- name: string,
4930
- ): Promise<{ worktreePath: string }> {
4931
- const hookInput = {
4932
- ...createBaseHookInput(undefined),
4933
- hook_event_name: 'WorktreeCreate' as const,
4934
- name,
4935
- }
4936
-
4937
- const results = await executeHooksOutsideREPL({
4938
- hookInput,
4939
- timeoutMs: TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4940
- })
4941
-
4942
- // Find the first successful result with non-empty output
4943
- const successfulResult = results.find(
4944
- r => r.succeeded && r.output.trim().length > 0,
4945
- )
4946
-
4947
- if (!successfulResult) {
4948
- const failedOutputs = results
4949
- .filter(r => !r.succeeded)
4950
- .map(r => `${r.command}: ${r.output.trim() || 'no output'}`)
4951
- throw new Error(
4952
- `WorktreeCreate hook failed: ${failedOutputs.join('; ') || 'no successful output'}`,
4953
- )
4954
- }
4955
-
4956
- const worktreePath = successfulResult.output.trim()
4957
- return { worktreePath }
4958
- }
4959
-
4960
- /**
4961
- * Execute WorktreeRemove hooks if configured.
4962
- * Returns true if hooks were configured and ran, false if no hooks are configured.
4963
- *
4964
- * Checks both settings-file hooks (getHooksConfigFromSnapshot) and registered
4965
- * hooks (plugin hooks + SDK callback hooks via registerHookCallbacks).
4966
- */
4967
- export async function executeWorktreeRemoveHook(
4968
- worktreePath: string,
4969
- ): Promise<boolean> {
4970
- const snapshotHooks = getHooksConfigFromSnapshot()?.['WorktreeRemove']
4971
- const registeredHooks = getRegisteredHooks()?.['WorktreeRemove']
4972
- const hasSnapshotHooks = snapshotHooks && snapshotHooks.length > 0
4973
- const hasRegisteredHooks = registeredHooks && registeredHooks.length > 0
4974
- if (!hasSnapshotHooks && !hasRegisteredHooks) {
4975
- return false
4976
- }
4977
-
4978
- const hookInput = {
4979
- ...createBaseHookInput(undefined),
4980
- hook_event_name: 'WorktreeRemove' as const,
4981
- worktree_path: worktreePath,
4982
- }
4983
-
4984
- const results = await executeHooksOutsideREPL({
4985
- hookInput,
4986
- timeoutMs: TOOL_HOOK_EXECUTION_TIMEOUT_MS,
4987
- })
4988
-
4989
- if (results.length === 0) {
4990
- return false
4991
- }
4992
-
4993
- for (const result of results) {
4994
- if (!result.succeeded) {
4995
- logForDebugging(
4996
- `WorktreeRemove hook failed [${result.command}]: ${result.output.trim()}`,
4997
- { level: 'error' },
4998
- )
4999
- }
5000
- }
5001
-
5002
- return true
5003
- }
5004
-
5005
- function getHookDefinitionsForTelemetry(
5006
- matchedHooks: MatchedHook[],
5007
- ): Array<{ type: string; command?: string; prompt?: string; name?: string }> {
5008
- return matchedHooks.map(({ hook }) => {
5009
- if (hook.type === 'command') {
5010
- return { type: 'command', command: hook.command }
5011
- } else if (hook.type === 'prompt') {
5012
- return { type: 'prompt', prompt: hook.prompt }
5013
- } else if (hook.type === 'http') {
5014
- return { type: 'http', command: hook.url }
5015
- } else if (hook.type === 'function') {
5016
- return { type: 'function', name: 'function' }
5017
- } else if (hook.type === 'callback') {
5018
- return { type: 'callback', name: 'callback' }
5019
- }
5020
- return { type: 'unknown' }
5021
- })
5022
- }