import { i as formatErrorMessage } from "./errors-Cq_Pdh35.js";
import { n as appendRegularFile } from "./fs-safe-CmlZlB6k.js";
import { t as privateFileStore } from "./private-file-store-CkExsGri.js";
import { t as emitSessionTranscriptUpdate } from "./transcript-events-Bdc3eBNy.js";
import { d as resolveSessionWriteLockOptions, i as acquireSessionWriteLock } from "./session-write-lock-_GKNo_Xi.js";
import "./transcript-jsonl-LFU2CQ2E.js";
import { c as parseSessionEntries, n as buildSessionContext, s as migrateSessionEntries } from "./session-manager-BvMIbDA_.js";
import "./sessions-BwnSmey5.js";
import { t as log } from "./logger-BXbMtoV0.js";
import path from "node:path";
import fs from "node:fs/promises";
import { randomUUID } from "node:crypto";
//#region src/agents/embedded-agent-runner/transcript-file-state.ts
const sessionEntryTypes = new Set([
	"branch_summary",
	"compaction",
	"custom",
	"custom_message",
	"label",
	"message",
	"model_change",
	"session_info",
	"thinking_level_change"
]);
const repairableToolCallContentTypes = new Set([
	"functionCall",
	"function_call",
	"toolCall",
	"toolUse",
	"tool_call",
	"tool_use"
]);
const invalidJsonlSlotType = "__openclaw_invalid_jsonl_slot";
function isRecord(value) {
	return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}
function isString(value) {
	return typeof value === "string" && value.trim() !== "";
}
function isOptionalString(value) {
	return value === void 0 || typeof value === "string";
}
function isTextContent(value) {
	return isRecord(value) && value.type === "text" && typeof value.text === "string" && isOptionalString(value.textSignature);
}
function isThinkingContent(value) {
	return isRecord(value) && value.type === "thinking" && typeof value.thinking === "string" && isOptionalString(value.thinkingSignature) && (value.redacted === void 0 || typeof value.redacted === "boolean");
}
function isImageContent(value) {
	return isRecord(value) && value.type === "image" && typeof value.data === "string" && typeof value.mimeType === "string";
}
function hasToolCallId(value) {
	return isString(value.id) || isString(value.call_id) || isString(value.toolCallId) || isString(value.toolUseId) || isString(value.tool_call_id) || isString(value.tool_use_id);
}
function isToolCallPayload(value) {
	return value === null || isRecord(value) || typeof value === "string";
}
function isToolCallContent(value) {
	return isRecord(value) && typeof value.type === "string" && repairableToolCallContentTypes.has(value.type) && hasToolCallId(value) && isString(value.name) && (value.arguments === void 0 || isToolCallPayload(value.arguments)) && (value.input === void 0 || isToolCallPayload(value.input)) && isOptionalString(value.thoughtSignature);
}
function isPersistedContentBlock(value) {
	if (!isRecord(value) || !isString(value.type)) return false;
	switch (value.type) {
		case "text": return isTextContent(value);
		case "thinking": return isThinkingContent(value);
		case "image": return isImageContent(value);
		default:
			if (repairableToolCallContentTypes.has(value.type)) return isToolCallContent(value);
			return true;
	}
}
function isUserContent(value) {
	return typeof value === "string" || Array.isArray(value) && value.every((item) => isPersistedContentBlock(item));
}
function isAssistantContent(value) {
	return typeof value === "string" || Array.isArray(value) && value.every((item) => isPersistedContentBlock(item));
}
function isToolResultContent(value) {
	return Array.isArray(value) && value.every((item) => isPersistedContentBlock(item));
}
function isOptionalBoolean(value) {
	return value === void 0 || typeof value === "boolean";
}
function isBashExecutionMessage(value) {
	return isString(value.command) && typeof value.output === "string" && (value.exitCode === void 0 || typeof value.exitCode === "number") && typeof value.cancelled === "boolean" && typeof value.truncated === "boolean" && isOptionalString(value.fullOutputPath) && isOptionalBoolean(value.excludeFromContext);
}
function isAgentMessage(value) {
	if (!isRecord(value)) return false;
	switch (value.role) {
		case "assistant": return isAssistantContent(value.content);
		case "bashExecution": return isBashExecutionMessage(value);
		case "custom": return isString(value.customType) && isUserContent(value.content);
		case "toolResult": return isString(value.toolCallId) && isString(value.toolName) && typeof value.isError === "boolean" && isToolResultContent(value.content);
		case "user": return isUserContent(value.content);
		default: return false;
	}
}
function hasSessionEntryBase(entry) {
	const candidate = entry;
	return isString(candidate.id) && (candidate.parentId === void 0 || candidate.parentId === null || isString(candidate.parentId)) && (candidate.timestamp === void 0 || isString(candidate.timestamp));
}
function isSessionEntry(entry) {
	if (entry.type === "session" || !sessionEntryTypes.has(entry.type) || !hasSessionEntryBase(entry)) return false;
	switch (entry.type) {
		case "branch_summary": {
			const candidate = entry;
			return isString(candidate.fromId) && typeof candidate.summary === "string";
		}
		case "compaction": {
			const candidate = entry;
			return isString(candidate.firstKeptEntryId) && typeof candidate.summary === "string" && typeof candidate.tokensBefore === "number";
		}
		case "custom": return isString(entry.customType);
		case "custom_message": {
			const candidate = entry;
			return isString(candidate.customType) && isUserContent(candidate.content) && typeof candidate.display === "boolean";
		}
		case "label": {
			const candidate = entry;
			return isString(candidate.targetId) && (candidate.label === void 0 || typeof candidate.label === "string");
		}
		case "message": return isAgentMessage(entry.message);
		case "model_change": {
			const candidate = entry;
			return isString(candidate.provider) && isString(candidate.modelId);
		}
		case "session_info": {
			const candidate = entry;
			return candidate.name === void 0 || typeof candidate.name === "string";
		}
		case "thinking_level_change": return isString(entry.thinkingLevel);
	}
	return false;
}
function readableSessionEntries(fileEntries) {
	const entries = [];
	const acceptedIds = /* @__PURE__ */ new Set();
	const acceptedEntryById = /* @__PURE__ */ new Map();
	const rejectedIds = /* @__PURE__ */ new Set();
	const rejectedParentById = /* @__PURE__ */ new Map();
	const firstReadableDescendantByRejectedId = /* @__PURE__ */ new Map();
	const rejectedAncestorsByAcceptedId = /* @__PURE__ */ new Map();
	const acceptedPath = (leafId) => {
		const path = [];
		let id = leafId ?? null;
		const seen = /* @__PURE__ */ new Set();
		while (id !== null) {
			if (seen.has(id)) break;
			seen.add(id);
			const entry = acceptedEntryById.get(id);
			if (!entry) break;
			path.unshift(entry);
			id = entry.parentId;
		}
		return path;
	};
	const firstReadableDescendantOnBranch = (rejectedId, leafId) => {
		for (const entry of acceptedPath(leafId)) if (rejectedAncestorsByAcceptedId.get(entry.id)?.includes(rejectedId)) return entry.id;
	};
	const rejectedParentChain = (parentId) => {
		const chain = [];
		let resolved = parentId ?? null;
		const seen = /* @__PURE__ */ new Set();
		while (resolved !== null && rejectedParentById.has(resolved)) {
			if (seen.has(resolved)) break;
			seen.add(resolved);
			chain.push(resolved);
			resolved = rejectedParentById.get(resolved) ?? null;
		}
		return chain;
	};
	const resolveRejectedParent = (parentId) => {
		let resolved = parentId ?? null;
		const seen = /* @__PURE__ */ new Set();
		while (resolved !== null && rejectedParentById.has(resolved)) {
			if (seen.has(resolved)) return null;
			seen.add(resolved);
			resolved = rejectedParentById.get(resolved) ?? null;
		}
		return resolved;
	};
	const repairEntryLinks = (entry) => {
		const rejectedAncestors = rejectedParentChain(entry.parentId);
		const resolvedRejectedParent = rejectedAncestors.length > 0 ? resolveRejectedParent(entry.parentId) : void 0;
		const parentId = resolvedRejectedParent !== void 0 ? resolvedRejectedParent !== null && acceptedIds.has(resolvedRejectedParent) ? resolvedRejectedParent : null : entry.parentId ?? null;
		let repaired = parentId === entry.parentId ? entry : {
			...entry,
			parentId
		};
		if (repaired.type === "compaction" && rejectedIds.has(repaired.firstKeptEntryId)) {
			const resolvedFirstKeptParent = resolveRejectedParent(repaired.firstKeptEntryId);
			const firstKeptEntryId = (resolvedFirstKeptParent !== null && acceptedIds.has(resolvedFirstKeptParent) ? resolvedFirstKeptParent : void 0) ?? firstReadableDescendantOnBranch(repaired.firstKeptEntryId, parentId) ?? firstReadableDescendantByRejectedId.get(repaired.firstKeptEntryId) ?? parentId;
			if (firstKeptEntryId !== null && firstKeptEntryId !== repaired.firstKeptEntryId) repaired = {
				...repaired,
				firstKeptEntryId
			};
		}
		if (repaired.type !== "compaction") {
			for (const rejectedId of rejectedAncestors) if (!firstReadableDescendantByRejectedId.has(rejectedId)) firstReadableDescendantByRejectedId.set(rejectedId, repaired.id);
			if (rejectedAncestors.length > 0) rejectedAncestorsByAcceptedId.set(repaired.id, rejectedAncestors);
		}
		return repaired;
	};
	for (const rawEntry of fileEntries) {
		if (!isRecord(rawEntry)) continue;
		const entry = rawEntry;
		const id = rawEntry.id;
		if (!isSessionEntry(entry)) {
			if (isString(id)) {
				rejectedIds.add(id);
				const parentId = rawEntry.parentId;
				rejectedParentById.set(id, isString(parentId) ? parentId : null);
			}
			continue;
		}
		if (entry.type === "label" && !acceptedIds.has(entry.targetId)) {
			rejectedIds.add(entry.id);
			rejectedParentById.set(entry.id, entry.parentId);
			continue;
		}
		if (acceptedIds.has(entry.id)) continue;
		const repaired = repairEntryLinks(entry);
		entries.push(repaired);
		acceptedIds.add(repaired.id);
		acceptedEntryById.set(repaired.id, repaired);
	}
	return entries;
}
function sessionHeaderVersion(header) {
	return typeof header?.version === "number" ? header.version : 1;
}
function generateEntryId(byId) {
	for (let attempt = 0; attempt < 100; attempt += 1) {
		const id = randomUUID().slice(0, 8);
		if (!byId.has(id)) return id;
	}
	return randomUUID();
}
function serializeTranscriptFileEntries(entries) {
	return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
}
function fileEntryOrMigrationSlot(value, index) {
	if (isRecord(value)) return value;
	return {
		type: invalidJsonlSlotType,
		id: `__openclaw_invalid_jsonl_slot_${index}`,
		parentId: null,
		timestamp: "1970-01-01T00:00:00.000Z"
	};
}
var TranscriptFileState = class {
	constructor(params) {
		this.byId = /* @__PURE__ */ new Map();
		this.labelsById = /* @__PURE__ */ new Map();
		this.labelTimestampsById = /* @__PURE__ */ new Map();
		this.leafId = null;
		this.header = params.header;
		this.entries = [...params.entries];
		this.migrated = params.migrated === true;
		this.rebuildIndex();
	}
	rebuildIndex() {
		this.byId.clear();
		this.labelsById.clear();
		this.labelTimestampsById.clear();
		this.leafId = null;
		for (const entry of this.entries) {
			this.byId.set(entry.id, entry);
			this.leafId = entry.id;
			if (entry.type === "label") if (entry.label) {
				this.labelsById.set(entry.targetId, entry.label);
				this.labelTimestampsById.set(entry.targetId, entry.timestamp);
			} else {
				this.labelsById.delete(entry.targetId);
				this.labelTimestampsById.delete(entry.targetId);
			}
		}
	}
	getCwd() {
		return this.header?.cwd ?? process.cwd();
	}
	getHeader() {
		return this.header;
	}
	getEntries() {
		return [...this.entries];
	}
	getLeafId() {
		return this.leafId;
	}
	getLeafEntry() {
		return this.leafId ? this.byId.get(this.leafId) : void 0;
	}
	getLabel(id) {
		return this.labelsById.get(id);
	}
	getBranch(fromId) {
		const branch = [];
		let current = fromId ?? this.leafId ? this.byId.get(fromId ?? this.leafId) : void 0;
		while (current) {
			branch.push(current);
			current = current.parentId ? this.byId.get(current.parentId) : void 0;
		}
		branch.reverse();
		return branch;
	}
	buildSessionContext() {
		return buildSessionContext(this.entries, this.leafId, this.byId);
	}
	branch(branchFromId) {
		if (!this.byId.has(branchFromId)) throw new Error(`Entry ${branchFromId} not found`);
		this.leafId = branchFromId;
	}
	resetLeaf() {
		this.leafId = null;
	}
	appendMessage(message) {
		return this.appendEntry({
			type: "message",
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			message
		});
	}
	appendThinkingLevelChange(thinkingLevel) {
		return this.appendEntry({
			type: "thinking_level_change",
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			thinkingLevel
		});
	}
	appendModelChange(provider, modelId) {
		return this.appendEntry({
			type: "model_change",
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			provider,
			modelId
		});
	}
	appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
		return this.appendEntry({
			type: "compaction",
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			summary,
			firstKeptEntryId,
			tokensBefore,
			details,
			fromHook
		});
	}
	appendCustomEntry(customType, data) {
		return this.appendEntry({
			type: "custom",
			customType,
			data,
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString()
		});
	}
	appendSessionInfo(name) {
		return this.appendEntry({
			type: "session_info",
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			name: name.trim()
		});
	}
	appendCustomMessageEntry(customType, content, display, details) {
		return this.appendEntry({
			type: "custom_message",
			customType,
			content,
			display,
			details,
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString()
		});
	}
	appendLabelChange(targetId, label) {
		if (!this.byId.has(targetId)) throw new Error(`Entry ${targetId} not found`);
		return this.appendEntry({
			type: "label",
			id: generateEntryId(this.byId),
			parentId: this.leafId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			targetId,
			label
		});
	}
	branchWithSummary(branchFromId, summary, details, fromHook) {
		if (branchFromId !== null && !this.byId.has(branchFromId)) throw new Error(`Entry ${branchFromId} not found`);
		this.leafId = branchFromId;
		return this.appendEntry({
			type: "branch_summary",
			id: generateEntryId(this.byId),
			parentId: branchFromId,
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			fromId: branchFromId ?? "root",
			summary,
			details,
			fromHook
		});
	}
	appendEntry(entry) {
		this.entries.push(entry);
		this.byId.set(entry.id, entry);
		this.leafId = entry.id;
		if (entry.type === "label") if (entry.label) {
			this.labelsById.set(entry.targetId, entry.label);
			this.labelTimestampsById.set(entry.targetId, entry.timestamp);
		} else {
			this.labelsById.delete(entry.targetId);
			this.labelTimestampsById.delete(entry.targetId);
		}
		return entry;
	}
};
async function readTranscriptFileState(sessionFile) {
	const fileEntries = parseSessionEntries(await fs.readFile(sessionFile, "utf-8")).map(fileEntryOrMigrationSlot);
	const migrated = sessionHeaderVersion(fileEntries.find((entry) => entry.type === "session") ?? null) < 3;
	migrateSessionEntries(fileEntries);
	return new TranscriptFileState({
		header: fileEntries.find((entry) => entry.type === "session") ?? null,
		entries: readableSessionEntries(fileEntries),
		migrated
	});
}
async function writeTranscriptFileAtomic(filePath, entries) {
	await privateFileStore(path.dirname(filePath)).writeText(path.basename(filePath), serializeTranscriptFileEntries(entries));
}
async function persistTranscriptStateMutation(params) {
	if (params.appendedEntries.length === 0 && !params.state.migrated) return;
	if (params.state.migrated) {
		await writeTranscriptFileAtomic(params.sessionFile, [...params.state.header ? [params.state.header] : [], ...params.state.entries]);
		return;
	}
	await appendRegularFile({
		filePath: params.sessionFile,
		content: `${params.appendedEntries.map((entry) => JSON.stringify(entry)).join("\n")}\n`,
		rejectSymlinkParents: true
	});
}
//#endregion
//#region src/agents/session-raw-append-message.ts
const RAW_APPEND_MESSAGE = Symbol("nodmix.session.rawAppendMessage");
/**
* Return the unguarded appendMessage implementation for a session manager.
*/
function getRawSessionAppendMessage(sessionManager) {
	return sessionManager[RAW_APPEND_MESSAGE] ?? sessionManager.appendMessage.bind(sessionManager);
}
function setRawSessionAppendMessage(sessionManager, appendMessage) {
	sessionManager[RAW_APPEND_MESSAGE] = appendMessage;
}
//#endregion
//#region src/agents/embedded-agent-runner/transcript-rewrite.ts
function estimateMessageBytes(message) {
	return Buffer.byteLength(JSON.stringify(message), "utf8");
}
function remapEntryId(entryId, rewrittenEntryIds) {
	if (!entryId) return null;
	return rewrittenEntryIds.get(entryId) ?? entryId;
}
function appendBranchEntry(params) {
	const { sessionManager, entry, rewrittenEntryIds, appendMessage } = params;
	if (entry.type === "message") return appendMessage(entry.message);
	if (entry.type === "compaction") return sessionManager.appendCompaction(entry.summary, remapEntryId(entry.firstKeptEntryId, rewrittenEntryIds) ?? entry.firstKeptEntryId, entry.tokensBefore, entry.details, entry.fromHook);
	if (entry.type === "thinking_level_change") return sessionManager.appendThinkingLevelChange(entry.thinkingLevel);
	if (entry.type === "model_change") return sessionManager.appendModelChange(entry.provider, entry.modelId);
	if (entry.type === "custom") return sessionManager.appendCustomEntry(entry.customType, entry.data);
	if (entry.type === "custom_message") return sessionManager.appendCustomMessageEntry(entry.customType, entry.content, entry.display, entry.details);
	if (entry.type === "session_info") {
		if (entry.name) return sessionManager.appendSessionInfo(entry.name);
		return sessionManager.appendSessionInfo("");
	}
	if (entry.type === "branch_summary") return sessionManager.branchWithSummary(remapEntryId(entry.parentId, rewrittenEntryIds), entry.summary, entry.details, entry.fromHook);
	return sessionManager.appendLabelChange(remapEntryId(entry.targetId, rewrittenEntryIds) ?? entry.targetId, entry.label);
}
function appendTranscriptStateBranchEntry(params) {
	const { state, entry, rewrittenEntryIds } = params;
	if (entry.type === "message") return state.appendMessage(entry.message);
	if (entry.type === "compaction") return state.appendCompaction(entry.summary, remapEntryId(entry.firstKeptEntryId, rewrittenEntryIds) ?? entry.firstKeptEntryId, entry.tokensBefore, entry.details, entry.fromHook);
	if (entry.type === "thinking_level_change") return state.appendThinkingLevelChange(entry.thinkingLevel);
	if (entry.type === "model_change") return state.appendModelChange(entry.provider, entry.modelId);
	if (entry.type === "custom") return state.appendCustomEntry(entry.customType, entry.data);
	if (entry.type === "custom_message") return state.appendCustomMessageEntry(entry.customType, entry.content, entry.display, entry.details);
	if (entry.type === "session_info") return state.appendSessionInfo(entry.name ?? "");
	if (entry.type === "branch_summary") return state.branchWithSummary(remapEntryId(entry.parentId, rewrittenEntryIds), entry.summary, entry.details, entry.fromHook);
	return state.appendLabelChange(remapEntryId(entry.targetId, rewrittenEntryIds) ?? entry.targetId, entry.label);
}
/**
* Safely rewrites transcript message entries on the active branch by branching
* from the first rewritten message's parent and re-appending the suffix.
*/
function rewriteTranscriptEntriesInSessionManager(params) {
	const replacementsById = new Map(params.replacements.filter((replacement) => replacement.entryId.trim().length > 0).map((replacement) => [replacement.entryId, replacement.message]));
	if (replacementsById.size === 0) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "no replacements requested"
	};
	const branch = params.sessionManager.getBranch();
	if (branch.length === 0) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "empty session"
	};
	const matchedIndices = [];
	let bytesFreed = 0;
	for (let index = 0; index < branch.length; index++) {
		const entry = branch[index];
		if (entry.type !== "message") continue;
		const replacement = replacementsById.get(entry.id);
		if (!replacement) continue;
		const originalBytes = estimateMessageBytes(entry.message);
		const replacementBytes = estimateMessageBytes(replacement);
		matchedIndices.push(index);
		bytesFreed += Math.max(0, originalBytes - replacementBytes);
	}
	if (matchedIndices.length === 0) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "no matching message entries"
	};
	const firstMatchedEntry = branch[matchedIndices[0]];
	if (!firstMatchedEntry) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "invalid first rewrite target"
	};
	if (!firstMatchedEntry.parentId) params.sessionManager.resetLeaf();
	else params.sessionManager.branch(firstMatchedEntry.parentId);
	const appendMessage = getRawSessionAppendMessage(params.sessionManager);
	const rewrittenEntryIds = /* @__PURE__ */ new Map();
	for (let index = matchedIndices[0]; index < branch.length; index++) {
		const entry = branch[index];
		const replacement = entry.type === "message" ? replacementsById.get(entry.id) : void 0;
		const newEntryId = replacement === void 0 ? appendBranchEntry({
			sessionManager: params.sessionManager,
			entry,
			rewrittenEntryIds,
			appendMessage
		}) : appendMessage(replacement);
		rewrittenEntryIds.set(entry.id, newEntryId);
	}
	return {
		changed: true,
		bytesFreed,
		rewrittenEntries: matchedIndices.length
	};
}
function rewriteTranscriptEntriesInState(params) {
	const replacementsById = new Map(params.replacements.filter((replacement) => replacement.entryId.trim().length > 0).map((replacement) => [replacement.entryId, replacement.message]));
	if (replacementsById.size === 0) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "no replacements requested",
		appendedEntries: []
	};
	const branch = params.state.getBranch();
	if (branch.length === 0) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "empty session",
		appendedEntries: []
	};
	const matchedIndices = [];
	let bytesFreed = 0;
	for (let index = 0; index < branch.length; index++) {
		const entry = branch[index];
		if (entry.type !== "message") continue;
		const replacement = replacementsById.get(entry.id);
		if (!replacement) continue;
		const originalBytes = estimateMessageBytes(entry.message);
		const replacementBytes = estimateMessageBytes(replacement);
		matchedIndices.push(index);
		bytesFreed += Math.max(0, originalBytes - replacementBytes);
	}
	if (matchedIndices.length === 0) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "no matching message entries",
		appendedEntries: []
	};
	const firstMatchedEntry = branch[matchedIndices[0]];
	if (!firstMatchedEntry) return {
		changed: false,
		bytesFreed: 0,
		rewrittenEntries: 0,
		reason: "invalid first rewrite target",
		appendedEntries: []
	};
	if (params.allowedRewriteSuffixEntryIds) {
		const allowedIds = new Set(params.allowedRewriteSuffixEntryIds);
		if (branch.slice(matchedIndices[0]).some((entry) => typeof entry.id === "string" && !allowedIds.has(entry.id))) return {
			changed: false,
			bytesFreed: 0,
			rewrittenEntries: 0,
			reason: "rewrite suffix guard failed",
			appendedEntries: []
		};
	}
	if (!firstMatchedEntry.parentId) params.state.resetLeaf();
	else params.state.branch(firstMatchedEntry.parentId);
	const appendedEntries = [];
	const rewrittenEntryIds = /* @__PURE__ */ new Map();
	for (let index = matchedIndices[0]; index < branch.length; index++) {
		const entry = branch[index];
		const replacement = entry.type === "message" ? replacementsById.get(entry.id) : void 0;
		const newEntry = replacement === void 0 ? appendTranscriptStateBranchEntry({
			state: params.state,
			entry,
			rewrittenEntryIds
		}) : params.state.appendMessage(replacement);
		rewrittenEntryIds.set(entry.id, newEntry.id);
		appendedEntries.push(newEntry);
	}
	return {
		changed: true,
		bytesFreed,
		rewrittenEntries: matchedIndices.length,
		appendedEntries
	};
}
/**
* Open a transcript file, rewrite message entries on the active branch, and
* emit a transcript update when the active branch changed.
*/
async function rewriteTranscriptEntriesInSessionFile(params) {
	let sessionLock;
	try {
		sessionLock = await acquireSessionWriteLock({
			sessionFile: params.sessionFile,
			...resolveSessionWriteLockOptions(params.config)
		});
		const state = await readTranscriptFileState(params.sessionFile);
		const result = rewriteTranscriptEntriesInState({
			state,
			replacements: params.request.replacements,
			...params.request.allowedRewriteSuffixEntryIds ? { allowedRewriteSuffixEntryIds: params.request.allowedRewriteSuffixEntryIds } : {}
		});
		if (result.changed) {
			await persistTranscriptStateMutation({
				sessionFile: params.sessionFile,
				state,
				appendedEntries: result.appendedEntries
			});
			emitSessionTranscriptUpdate({
				sessionFile: params.sessionFile,
				sessionKey: params.sessionKey,
				...params.agentId ? { agentId: params.agentId } : {}
			});
			log.info(`[transcript-rewrite] rewrote ${result.rewrittenEntries} entr${result.rewrittenEntries === 1 ? "y" : "ies"} bytesFreed=${result.bytesFreed} sessionKey=${params.sessionKey ?? params.sessionId ?? "unknown"}`);
		}
		return result;
	} catch (err) {
		const reason = formatErrorMessage(err);
		log.warn(`[transcript-rewrite] failed: ${reason}`);
		return {
			changed: false,
			bytesFreed: 0,
			rewrittenEntries: 0,
			reason
		};
	} finally {
		await sessionLock?.release();
	}
}
//#endregion
export { setRawSessionAppendMessage as a, readTranscriptFileState as c, getRawSessionAppendMessage as i, writeTranscriptFileAtomic as l, rewriteTranscriptEntriesInSessionManager as n, TranscriptFileState as o, rewriteTranscriptEntriesInState as r, persistTranscriptStateMutation as s, rewriteTranscriptEntriesInSessionFile as t };
