import { HOOK_EXECUTION_MODES } from "./types/hooks.js";
//#region src/extensions/hooks.ts
var ExtensionHookRunner = class {
	registry;
	options;
	constructor(registry, options) {
		this.registry = registry;
		this.options = options || {};
	}
	getRegistry() {
		return this.registry;
	}
	async runHooks(event, eventData, context) {
		const handlers = this.registry.getHooks(event);
		const results = [];
		for (const handler of handlers) try {
			const result = await handler(eventData, context);
			results.push({
				success: true,
				result
			});
		} catch (error) {
			results.push({
				success: false,
				error: error instanceof Error ? error.message : String(error)
			});
			if (!this.options.catchErrors) throw error;
			this.options.logger?.error?.(`Hook error in ${event}: ${error instanceof Error ? error.message : String(error)}`);
		}
		return {
			success: true,
			results
		};
	}
	async runHooksWithResult(event, eventData, context) {
		const handlers = this.registry.getHooks(event);
		let modifiedData = { ...eventData };
		for (const handler of handlers) try {
			const result = await handler(modifiedData, context);
			if (result && typeof result === "object") modifiedData = {
				...modifiedData,
				...result
			};
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`Hook modification error: ${error}`);
		}
		return modifiedData;
	}
	async runBeforeToolCall(toolName, params, context) {
		const event = {
			...context,
			toolName,
			params,
			timestamp: /* @__PURE__ */ new Date()
		};
		const handlers = this.registry.getHooks("before_tool_call");
		let modifiedParams = { ...params };
		let blocked = false;
		let blockReason;
		for (const handler of handlers) try {
			const result = await handler(event, context);
			if (result && typeof result === "object") {
				const typedResult = result;
				if (typedResult.block) {
					blocked = true;
					blockReason = typedResult.blockReason;
				}
				if (typedResult.params) modifiedParams = typedResult.params;
			}
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`before_tool_call hook error: ${error}`);
		}
		if (blocked) return {
			allowed: false,
			reason: blockReason
		};
		return {
			allowed: true,
			params: modifiedParams
		};
	}
	async runMessageSending(to, content, context, opts) {
		const event = {
			...context,
			to,
			content,
			channel: opts?.channel,
			timestamp: /* @__PURE__ */ new Date()
		};
		const handlers = this.registry.getHooks("message_sending");
		let modifiedContent = content;
		let cancelled = false;
		let cancelReason;
		for (const handler of handlers) try {
			const result = await handler(event, context);
			if (result && typeof result === "object") {
				const typedResult = result;
				if (typedResult.cancel) {
					cancelled = true;
					cancelReason = typedResult.cancelReason;
				}
				if (typedResult.content) modifiedContent = typedResult.content;
			}
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`message_sending hook error: ${error}`);
		}
		if (cancelled) return {
			send: false,
			reason: cancelReason
		};
		return {
			send: true,
			content: modifiedContent
		};
	}
	async runMessageSent(to, content, success, error, context, opts) {
		const event = {
			...context,
			to,
			content,
			success,
			error,
			channel: opts?.channel,
			timestamp: /* @__PURE__ */ new Date()
		};
		const handlers = this.registry.getHooks("message_sent");
		for (const handler of handlers) try {
			await handler(event, context);
		} catch (err) {
			if (!this.options.catchErrors) throw err;
			this.options.logger?.warn?.(`message_sent hook error: ${err instanceof Error ? err.message : String(err)}`);
		}
	}
	async runContextHook(messages, context) {
		const handlers = this.registry.getHooks("context");
		if (handlers.length === 0) return {
			messages,
			modified: false
		};
		let currentMessages = [...messages];
		let modified = false;
		const event = {
			messages: currentMessages,
			timestamp: /* @__PURE__ */ new Date(),
			...context
		};
		for (const handler of handlers) try {
			const result = await handler(event, context || {});
			if (result && typeof result === "object" && "messages" in result) {
				currentMessages = result.messages;
				event.messages = currentMessages;
				modified = true;
			}
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`context hook error: ${error instanceof Error ? error.message : String(error)}`);
		}
		return {
			messages: currentMessages,
			modified
		};
	}
	async runInputHook(text, images, source, context) {
		const handlers = this.registry.getHooks("input");
		if (handlers.length === 0) return {
			text,
			images,
			action: "continue",
			skipAgent: false
		};
		let currentText = text;
		let currentImages = images;
		const event = {
			text: currentText,
			images: currentImages,
			source,
			timestamp: /* @__PURE__ */ new Date(),
			...context
		};
		for (const handler of handlers) try {
			const result = await handler(event, context || {});
			if (result && typeof result === "object") {
				const typedResult = result;
				if (typedResult.action === "transform") {
					if (typedResult.text !== void 0) {
						currentText = typedResult.text;
						event.text = currentText;
					}
					if (typedResult.images !== void 0) {
						currentImages = typedResult.images;
						event.images = currentImages;
					}
					continue;
				}
				if (typedResult.action === "handled") return {
					text: currentText,
					images: currentImages,
					action: "handled",
					skipAgent: true,
					response: typedResult.response
				};
			}
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`input hook error: ${error instanceof Error ? error.message : String(error)}`);
		}
		return {
			text: currentText,
			images: currentImages,
			action: "continue",
			skipAgent: false
		};
	}
	async runVoidHook(hookName, eventData, context) {
		const handlers = this.registry.getHooks(hookName);
		if (handlers.length === 0) return;
		await Promise.allSettled(handlers.map(async (handler) => {
			try {
				await handler(eventData, context);
			} catch (error) {
				if (!this.options.catchErrors) throw error;
				this.options.logger?.warn?.(`Void hook error in ${hookName}: ${error instanceof Error ? error.message : String(error)}`);
			}
		}));
	}
	async runModifyingHook(hookName, eventData, context, merge) {
		const handlers = this.registry.getHooks(hookName);
		if (handlers.length === 0) return void 0;
		let result;
		for (const handler of handlers) try {
			const handlerResult = await handler(eventData, context);
			if (handlerResult && typeof handlerResult === "object") {
				if (merge && result) result = merge(result, handlerResult);
				else if (!result) result = handlerResult;
			}
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`Modifying hook error in ${hookName}: ${error instanceof Error ? error.message : String(error)}`);
		}
		return result;
	}
	async runClaimingHook(hookName, eventData, context) {
		const handlers = this.registry.getHooks(hookName);
		for (const handler of handlers) try {
			const result = await handler(eventData, context);
			if (result && typeof result === "object" && "handled" in result) {
				if (result.handled) return {
					handled: true,
					result
				};
			}
		} catch (error) {
			if (!this.options.catchErrors) throw error;
			this.options.logger?.warn?.(`Claiming hook error in ${hookName}: ${error instanceof Error ? error.message : String(error)}`);
		}
		return { handled: false };
	}
	async runHooksByMode(hookName, eventData, context) {
		switch (HOOK_EXECUTION_MODES[hookName]) {
			case "void":
				await this.runVoidHook(hookName, eventData, context);
				return { success: true };
			case "modifying": return {
				success: true,
				result: await this.runModifyingHook(hookName, eventData, context)
			};
			case "claiming": return {
				success: true,
				result: await this.runClaimingHook(hookName, eventData, context)
			};
			default: return { success: (await this.runHooks(hookName, eventData, context)).success };
		}
	}
};
function createHookContext(overrides) {
	return {
		timestamp: /* @__PURE__ */ new Date(),
		...overrides
	};
}
function isHookEvent(value) {
	return [
		"before_agent_start",
		"agent_end",
		"before_compaction",
		"after_compaction",
		"message_received",
		"message_sending",
		"message_sent",
		"before_tool_call",
		"after_tool_call",
		"session_start",
		"session_end",
		"gateway_start",
		"gateway_stop",
		"context",
		"input",
		"turn_start",
		"turn_end",
		"tool_execution_start",
		"tool_execution_update",
		"tool_execution_end",
		"before_model_resolve",
		"before_prompt_build",
		"llm_input",
		"llm_output",
		"inbound_claim",
		"before_reset",
		"before_message_write",
		"subagent_spawning",
		"subagent_delivery_target",
		"subagent_ended",
		"webchat_turn_complete"
	].includes(value);
}
//#endregion
export { ExtensionHookRunner, createHookContext, isHookEvent };

//# sourceMappingURL=hooks.js.map