( toolUseContext: ToolUseContext, tool: Tool<Input, unknown>, toolUseID: string, messageId: string, processedInput: z.infer<Input>, error: string, isInterrupt: boolean | undefined, requestId: string | undefined, mcpServerType: McpServerType, mcpServerBaseUrl: string | undefined, )
| 191 | } |
| 192 | |
| 193 | export async function* runPostToolUseFailureHooks<Input extends AnyObject>( |
| 194 | toolUseContext: ToolUseContext, |
| 195 | tool: Tool<Input, unknown>, |
| 196 | toolUseID: string, |
| 197 | messageId: string, |
| 198 | processedInput: z.infer<Input>, |
| 199 | error: string, |
| 200 | isInterrupt: boolean | undefined, |
| 201 | requestId: string | undefined, |
| 202 | mcpServerType: McpServerType, |
| 203 | mcpServerBaseUrl: string | undefined, |
| 204 | ): AsyncGenerator< |
| 205 | MessageUpdateLazy<AttachmentMessage | ProgressMessage<HookProgress>> |
| 206 | > { |
| 207 | const postToolStartTime = Date.now() |
| 208 | try { |
| 209 | const appState = toolUseContext.getAppState() |
| 210 | const permissionMode = appState.toolPermissionContext.mode |
| 211 | |
| 212 | for await (const result of executePostToolUseFailureHooks( |
| 213 | tool.name, |
| 214 | toolUseID, |
| 215 | processedInput, |
| 216 | error, |
| 217 | toolUseContext, |
| 218 | isInterrupt, |
| 219 | permissionMode, |
| 220 | toolUseContext.abortController.signal, |
| 221 | )) { |
| 222 | try { |
| 223 | // Check if we were aborted during hook execution |
| 224 | if ( |
| 225 | result.message?.type === 'attachment' && |
| 226 | result.message.attachment.type === 'hook_cancelled' |
| 227 | ) { |
| 228 | logEvent('tengu_post_tool_failure_hooks_cancelled', { |
| 229 | toolName: sanitizeToolNameForAnalytics(tool.name), |
| 230 | queryChainId: toolUseContext.queryTracking |
| 231 | ?.chainId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 232 | queryDepth: toolUseContext.queryTracking?.depth, |
| 233 | }) |
| 234 | yield { |
| 235 | message: createAttachmentMessage({ |
| 236 | type: 'hook_cancelled', |
| 237 | hookName: `PostToolUseFailure:${tool.name}`, |
| 238 | toolUseID, |
| 239 | hookEvent: 'PostToolUseFailure', |
| 240 | }), |
| 241 | } |
| 242 | continue |
| 243 | } |
| 244 | |
| 245 | // Skip hook_blocking_error in result.message — blockingError path |
| 246 | // below creates the same attachment (see #31301 / PostToolUse above). |
| 247 | if ( |
| 248 | result.message && |
| 249 | !( |
| 250 | result.message.type === 'attachment' && |
no test coverage detected