import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
import { appendPiTranscriptMessage } from "../../session/parity/jsonl-transcript-io.js";
import { handlePersistentGoalPostTurn } from "./post-turn.js";
//#region src/agent/goals/persistent-goal-service.ts
init_session_key();
init_logger();
const log = createLogger("PersistentGoalService");
var PersistentGoalService = class {
	opts;
	/** Gateway only: webchat continuations bypass the bus and reuse `runGatewayAgent`. */
	webchatContinuationScheduler;
	constructor(opts) {
		this.opts = opts;
	}
	/** Register the gateway-side webchat continuation hook (set from `web-agent` wiring). */
	setWebchatContinuationScheduler(fn) {
		this.webchatContinuationScheduler = fn;
	}
	/**
	* Continue a session after `/goal` decides the previous turn needs follow-up.
	* Webchat sessions go through the scheduler; bus-driven channels re-publish the
	* follow-up message as an inbound bus event so the existing inbound loop picks it up.
	*/
	scheduleContinuation(sessionKey, message, routing) {
		if (parseSessionKey(sessionKey)?.source === "webchat" && this.webchatContinuationScheduler) {
			this.webchatContinuationScheduler(sessionKey, message);
			return;
		}
		queueMicrotask(() => {
			this.opts.bus.publishInbound({
				channel: routing.channel,
				chat_id: routing.chatId,
				sender_id: "persistent-goal",
				content: message,
				metadata: {
					sessionKey,
					...routing.inboundMetadata
				}
			}).catch((err) => {
				log.warn({
					err,
					sessionKey
				}, "Persistent goal: publishInbound failed");
			});
		});
	}
	/** Build the per-command `PersistentGoalApis` bag (transcript writers + scheduler closures). */
	buildApisForRouting(routing) {
		return {
			getSessionMetadata: (k) => this.opts.sessionStore.getMetadata(k),
			updateSessionMetadata: async (k, u) => {
				await this.opts.sessionStore.updateMetadata(k, u);
				this.opts.onSessionMetadataUpdated?.(k);
			},
			loadMessages: (k) => this.opts.sessionStore.loadMessages(k),
			appendAssistantReceipt: async (k, text) => {
				const trimmed = text.trim();
				if (!trimmed) return;
				const { absPath } = await this.opts.sessionStore.resolveTranscriptPath(k);
				await appendPiTranscriptMessage({
					absPath,
					cwd: this.opts.getResolvedWorkspaceForSession(k),
					message: {
						role: "assistant",
						content: [{
							type: "text",
							text: trimmed
						}],
						timestamp: Date.now()
					},
					sessionKey: k
				});
				this.opts.notifyWebchatTranscriptAppend(k, trimmed);
			},
			scheduleContinuation: (sk, msg) => {
				this.scheduleContinuation(sk, msg, {
					channel: routing.channel,
					chatId: routing.chatId,
					inboundMetadata: routing.inboundMetadata
				});
			},
			inboundConcurrentDepth: (sk) => this.opts.sessionState.getInboundTurnDepth(sk)
		};
	}
	recordStreamOutcome(sessionKey, outcome) {
		this.opts.sessionState.recordPersistentGoalStreamOutcome(sessionKey, outcome);
	}
	takeStreamOutcome(sessionKey) {
		return this.opts.sessionState.takePersistentGoalStreamOutcome(sessionKey);
	}
	/**
	* Run the `/goal` post-turn verdict for a completed user turn (called from
	* `OutboundCoordinator.emitSessionTurnComplete`).
	*/
	async runPostTurn(payload) {
		const apis = this.buildApisForRouting({
			sessionKey: payload.sessionKey,
			channel: payload.channel,
			chatId: payload.chatId,
			inboundMetadata: payload.outboundMetadata
		});
		const publishVerdict = !(parseSessionKey(payload.sessionKey)?.source === "webchat") && payload.channel !== "cli" ? async (text) => {
			await this.opts.bus.publishOutbound({
				channel: payload.channel,
				chat_id: payload.chatId,
				content: text,
				type: "message",
				metadata: {
					accountId: payload.outboundMetadata?.accountId,
					threadId: payload.outboundMetadata?.threadId
				}
			});
		} : void 0;
		let runtimeSessionModelRef;
		try {
			runtimeSessionModelRef = this.opts.modelManager.getModelForSession(payload.sessionKey);
		} catch {
			runtimeSessionModelRef = void 0;
		}
		await handlePersistentGoalPostTurn({
			apis,
			sessionKey: payload.sessionKey,
			assistantPlainText: payload.assistantPlainText,
			aborted: payload.aborted,
			...payload.streamError !== void 0 ? { streamError: payload.streamError } : {},
			skipPersistentGoalPostTurn: payload.skipPersistentGoalPostTurn ?? false,
			config: this.opts.getConfig(),
			runtimeSessionModelRef,
			publishVerdictToChannel: publishVerdict
		});
	}
};
//#endregion
export { PersistentGoalService };

//# sourceMappingURL=persistent-goal-service.js.map