import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { extractTextContent } from "../context/workspace.js";
//#region src/agent/orchestration/agent-event-handler.ts
init_logger();
const log = createLogger("AgentEventHandler");
/**
* Typed pub/sub for agent events. Listeners run in registration order; the bus
* itself is synchronous — listeners that need async work must dispatch their own
* promises (typically by awaiting and logging on error, like the lifecycle hooks).
*/
var SessionEventBus = class {
	listeners = /* @__PURE__ */ new Map();
	on(type, listener) {
		const bucket = this.listeners.get(type) ?? [];
		bucket.push(listener);
		this.listeners.set(type, bucket);
		return () => {
			const current = this.listeners.get(type);
			if (!current) return;
			const idx = current.indexOf(listener);
			if (idx >= 0) current.splice(idx, 1);
		};
	}
	dispatch(event, context) {
		if (!context) {
			if (event.type !== "message_update") log.warn({ eventType: event.type }, `Agent event ignored (no SessionContext): ${event.type}`);
			return;
		}
		const exact = this.listeners.get(event.type);
		if (exact) for (const listener of exact) listener(event, context);
		const all = this.listeners.get("all");
		if (all) for (const listener of all) listener(event, context);
	}
};
function installProgressListener(bus, progressManager) {
	bus.on("agent_start", () => {
		log.debug("Agent turn started");
		progressManager.startTask();
	});
	bus.on("turn_start", () => {
		log.debug("Turn started");
		progressManager.onTurnStart();
	});
	bus.on("tool_execution_start", (event) => {
		const e = event;
		log.debug({
			tool: e.toolName,
			args: e.args
		}, "Tool execution started");
		progressManager.onToolStart(e.toolName, e.args || {});
	});
	bus.on("tool_execution_update", (event) => {
		const e = event;
		progressManager.onToolUpdate(e.toolName, e.partialResult);
	});
	bus.on("tool_execution_end", (event) => {
		const e = event;
		log.debug({
			tool: e.toolName,
			isError: e.isError
		}, "Tool execution complete");
		progressManager.onToolEnd(e.toolName, e.result, e.isError);
	});
	bus.on("agent_end", () => {
		progressManager.endTask();
	});
}
function installRequestLimitListener(bus, deps) {
	bus.on("agent_start", (_event, context) => {
		const result = deps.requestLimiter.recordRequest();
		deps.lifecycleManager.emit("llm_request", context.sessionKey, {
			requestNumber: result.count,
			maxRequests: result.limit
		}, context).catch((err) => {
			const em = err instanceof Error ? err.message : String(err);
			log.warn({
				err,
				errorMessage: em,
				sessionKey: context.sessionKey,
				requestNumber: result.count,
				maxRequests: result.limit
			}, `Lifecycle emit llm_request failed: ${em}`);
		});
		deps.progressManager.onRequestLimitStatus(result.count, result.limit, result.remaining, result.isWarning, result.shouldStop);
		if (result.shouldStop) log.error({
			count: result.count,
			limit: result.limit,
			sessionKey: context.sessionKey
		}, `Request limit reached (${result.count}/${result.limit}) for session`);
	});
	bus.on("turn_end", () => {
		deps.requestLimiter.reset();
	});
}
function installLifecycleHookListener(bus, lifecycleManager) {
	bus.on("message_end", (event, context) => {
		const e = event;
		if (e.message?.role !== "assistant") return;
		const content = e.message.content;
		const text = Array.isArray(content) ? extractTextContent(content) : String(content);
		log.debug({ contentLength: text.length }, "Assistant response complete");
		lifecycleManager.emit("llm_response", context.sessionKey, {
			response: text,
			usage: e.message.usage
		}, context).catch((err) => {
			const em = err instanceof Error ? err.message : String(err);
			log.warn({
				err,
				errorMessage: em,
				sessionKey: context.sessionKey,
				responseChars: text.length
			}, `Lifecycle emit llm_response failed: ${em}`);
		});
	});
	bus.on("tool_execution_start", (event, context) => {
		const e = event;
		lifecycleManager.emit("tool_call_start", context.sessionKey, {
			toolName: e.toolName,
			arguments: e.args || {},
			attemptNumber: 1,
			maxAttempts: 3
		}, context).catch((err) => {
			const em = err instanceof Error ? err.message : String(err);
			log.warn({
				err,
				errorMessage: em,
				sessionKey: context.sessionKey,
				tool: e.toolName
			}, `Lifecycle emit tool_call_start failed: ${em}`);
		});
	});
	bus.on("tool_execution_end", (event, context) => {
		const e = event;
		const durationMs = e.durationMs || 0;
		lifecycleManager.emit("tool_call_end", context.sessionKey, {
			toolName: e.toolName,
			success: !e.isError,
			result: e.result,
			error: e.isError ? String(e.result) : void 0,
			durationMs
		}, context).catch((err) => {
			const em = err instanceof Error ? err.message : String(err);
			log.warn({
				err,
				errorMessage: em,
				sessionKey: context.sessionKey,
				tool: e.toolName
			}, `Lifecycle hook tool_call_end failed: ${em}`);
		});
	});
}
function installSystemReminderListener(bus, systemReminder) {
	bus.on("tool_execution_end", (event) => {
		const e = event;
		e.result = systemReminder.appendToResult(e.result);
	});
}
function installToolChainListener(bus, toolChainTracker) {
	bus.on("turn_start", (_event, context) => {
		toolChainTracker.startChain(context.sessionKey);
	});
	bus.on("tool_execution_start", (event, context) => {
		const e = event;
		toolChainTracker.recordCall(context.sessionKey, e.toolName, e.args || {}, 0);
	});
	bus.on("tool_execution_end", (event, context) => {
		const e = event;
		const durationMs = e.durationMs || 0;
		const chain = toolChainTracker.getCurrentChain(context.sessionKey);
		if (!chain) return;
		const lastNode = chain.nodes[chain.nodes.length - 1];
		if (lastNode && lastNode.toolName === e.toolName) toolChainTracker.recordResult(context.sessionKey, lastNode.id, e.result, e.isError ? "Tool execution failed" : void 0, durationMs);
	});
	bus.on("turn_end", (_event, context) => {
		toolChainTracker.endChain(context.sessionKey);
	});
}
function installToolUsageListener(bus, toolUsageAnalyzer) {
	bus.on("tool_execution_end", (event) => {
		const e = event;
		const durationMs = e.durationMs || 0;
		toolUsageAnalyzer.recordUsage(e.toolName, !e.isError, durationMs);
	});
}
function extractErrorText(result) {
	if (typeof result === "string") return result;
	if (result && typeof result === "object") {
		const obj = result;
		if (typeof obj.error === "string") return obj.error;
		if (typeof obj.message === "string") return obj.message;
		return JSON.stringify(result);
	}
	return String(result);
}
function installErrorTrackingListener(bus, deps) {
	bus.on("tool_execution_end", (event) => {
		const e = event;
		if (!e.isError) return;
		const errorText = extractErrorText(e.result);
		deps.errorTracker.recordFailure(e.toolName, errorText);
		const errorMatch = deps.errorPatternMatcher.matchError(errorText);
		if (errorMatch.matched && errorMatch.pattern) {
			const preview = errorText.length > 120 ? `${errorText.slice(0, 120)}…` : errorText;
			log.warn({
				tool: e.toolName,
				pattern: errorMatch.pattern.name,
				errorPreview: preview
			}, `Tool error matched pattern "${errorMatch.pattern.name}" (${e.toolName}): ${preview}`);
		}
	});
	bus.on("turn_end", () => {
		deps.errorTracker.reset();
	});
}
function installSelfVerifyListener(bus, selfVerifyMiddleware) {
	bus.on("tool_execution_start", (event) => {
		const e = event;
		const args = e.args;
		const toolName = e.toolName;
		if (!toolName || !args) return;
		const name = toolName.toLowerCase();
		if (name.includes("write") && args.path) selfVerifyMiddleware.recordEdit(String(args.path), "write");
		else if (name.includes("edit") && args.path) selfVerifyMiddleware.recordEdit(String(args.path), "edit");
	});
	bus.on("turn_end", () => {
		selfVerifyMiddleware.onTurnStart();
	});
}
/**
* Thin façade over {@link SessionEventBus} that pre-registers all built-in
* listeners in their required order. `handle(event, ctx)` is the entry point
* used by `AgentService.handleSessionEvent`; extensions can hook in via
* {@link registerListener} without touching this class.
*/
var AgentEventHandler = class {
	bus;
	constructor(config) {
		this.bus = new SessionEventBus();
		installProgressListener(this.bus, config.progressManager);
		installRequestLimitListener(this.bus, {
			requestLimiter: config.requestLimiter,
			progressManager: config.progressManager,
			lifecycleManager: config.lifecycleManager
		});
		installLifecycleHookListener(this.bus, config.lifecycleManager);
		installSystemReminderListener(this.bus, config.systemReminder);
		installToolUsageListener(this.bus, config.toolUsageAnalyzer);
		installToolChainListener(this.bus, config.toolChainTracker);
		installErrorTrackingListener(this.bus, {
			errorTracker: config.errorTracker,
			errorPatternMatcher: config.errorPatternMatcher
		});
		installSelfVerifyListener(this.bus, config.selfVerifyMiddleware);
	}
	/** Dispatch a pi-agent event to all registered listeners. */
	handle(event, context) {
		this.bus.dispatch(event, context);
	}
	/**
	* Register an additional listener (e.g. from an extension). Returns an
	* unsubscribe function. Listeners run after the built-ins in registration
	* order; if you need to run before a built-in, you must create your own
	* {@link SessionEventBus} instance.
	*/
	registerListener(type, listener) {
		return this.bus.on(type, listener);
	}
};
//#endregion
export { AgentEventHandler, SessionEventBus };

//# sourceMappingURL=agent-event-handler.js.map