import path from "node:path";
import { AsyncLocalStorage } from "node:async_hooks";
//#region src/config/sessions/transcript-write-context.ts
const ownedTranscriptWriteContext = new AsyncLocalStorage();
function normalizeConcretePathForCompare(value) {
	const trimmed = value?.trim();
	if (!trimmed || !path.isAbsolute(trimmed) || !trimmed.endsWith(".jsonl")) return;
	return path.resolve(trimmed);
}
function contextMatches(params) {
	const normalizeTarget = (target) => {
		const agentId = target?.agentId?.trim();
		const sessionId = target?.sessionId?.trim();
		const sessionKey = target?.sessionKey?.trim();
		const storePath = target?.storePath?.trim();
		return sessionKey && storePath ? {
			agentId,
			sessionId,
			sessionKey,
			storePath: path.resolve(storePath)
		} : void 0;
	};
	const contextTarget = normalizeTarget(params.context.sessionTarget);
	const requestedTarget = normalizeTarget(params.sessionTarget);
	if (params.context.sessionTarget || params.sessionTarget) return Boolean(contextTarget && requestedTarget && contextTarget.sessionKey === requestedTarget.sessionKey && contextTarget.storePath === requestedTarget.storePath && (!contextTarget.agentId || !requestedTarget.agentId || contextTarget.agentId === requestedTarget.agentId) && (!contextTarget.sessionId || !requestedTarget.sessionId || contextTarget.sessionId === requestedTarget.sessionId));
	const contextSessionFile = normalizeConcretePathForCompare(params.context.sessionFile);
	const sessionFile = normalizeConcretePathForCompare(params.sessionFile);
	if (contextSessionFile && sessionFile) return contextSessionFile === sessionFile;
	const contextSessionKey = params.context.sessionKey?.trim();
	const sessionKey = params.sessionKey?.trim();
	return Boolean(contextSessionKey && sessionKey && contextSessionKey === sessionKey);
}
/** Runs transcript writes with the admitted run's teardown and writer-fence context. */
async function withOwnedSessionTranscriptWrites(context, run) {
	return await ownedTranscriptWriteContext.run(context, run);
}
/** Runs detached work without retaining an attempt-owned transcript context. */
function runWithoutOwnedSessionTranscriptWrites(run) {
	return ownedTranscriptWriteContext.exit(run);
}
function bindOwnedSessionTranscriptWrites(context, run) {
	return (...args) => ownedTranscriptWriteContext.run(context, () => run(...args));
}
/** Returns the matching admitted-run fence for a durable write boundary. */
function getOwnedSessionTranscriptWriterFence(params = {}) {
	const context = ownedTranscriptWriteContext.getStore();
	if (!context || Object.keys(params).length > 0 && !contextMatches({
		context,
		...params
	})) return;
	const initial = context.initialWriter;
	if (initial) return initial.committedFence ?? {
		expectedLifecycleRevision: void 0,
		expectedWriterRunId: initial.writerRunId
	};
	const target = context.sessionTarget;
	const expectedWriterRunId = target?.expectedWriterRunId?.trim();
	return expectedWriterRunId ? {
		expectedLifecycleRevision: target?.expectedLifecycleRevision,
		expectedWriterRunId
	} : void 0;
}
/** Inherit only the exact host-minted first-insert owner across attempt preparation. */
function getOwnedSessionTranscriptInitialWriter(params) {
	const context = ownedTranscriptWriteContext.getStore();
	if (!context?.initialWriter) return;
	if (!contextMatches({
		context,
		...params
	}) || context.sessionTarget?.sessionId !== params.sessionTarget?.sessionId || context.sessionTarget?.agentId !== params.sessionTarget?.agentId) throw new SessionTranscriptWriterClaimReboundError();
	return context.initialWriter;
}
function assertTranscriptWriteContext(context, scope) {
	if (!context?.assertCommitAllowed && !context?.initialWriter) return;
	if (!contextMatches({
		context,
		sessionTarget: scope
	}) || context.sessionTarget?.sessionId !== scope.sessionId || context.sessionTarget?.agentId !== scope.agentId) throw new SessionTranscriptWriterClaimReboundError();
	context.assertCommitAllowed?.();
	context.initialWriter?.assertActive();
}
/** A guarded context cannot silently become an unfenced write to another target. */
function assertOwnedTranscriptWriteCommit(scope) {
	assertTranscriptWriteContext(ownedTranscriptWriteContext.getStore(), scope);
}
/** Retained post-commit work must revalidate its original owner, not its invocation context. */
function captureOwnedTranscriptWriteAssertion(scope) {
	const context = ownedTranscriptWriteContext.getStore();
	const target = { ...scope };
	return () => assertTranscriptWriteContext(context, target);
}
/** Applies the admitted-run fence inherited by a matching synchronous writer. */
function withOwnedSessionTranscriptWriterFence(scope) {
	const fence = getOwnedSessionTranscriptWriterFence({
		sessionKey: scope.sessionKey,
		sessionTarget: scope
	});
	return fence ? {
		...scope,
		...fence
	} : scope;
}
var SessionTranscriptWriterClaimReboundError = class extends Error {
	constructor(cause) {
		super("session writer claim changed before transcript persistence", { cause });
		this.name = "SessionTranscriptWriterClaimReboundError";
	}
};
async function runWithOwnedSessionTranscriptWrite(params, run) {
	const context = ownedTranscriptWriteContext.getStore();
	if (!context || !contextMatches({
		context,
		...params
	})) return await run();
	return await context.withTranscriptWrite(run);
}
//#endregion
export { getOwnedSessionTranscriptInitialWriter as a, runWithoutOwnedSessionTranscriptWrites as c, captureOwnedTranscriptWriteAssertion as i, withOwnedSessionTranscriptWriterFence as l, assertOwnedTranscriptWriteCommit as n, getOwnedSessionTranscriptWriterFence as o, bindOwnedSessionTranscriptWrites as r, runWithOwnedSessionTranscriptWrite as s, SessionTranscriptWriterClaimReboundError as t, withOwnedSessionTranscriptWrites as u };
