UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

1,016 lines • 50.6 kB
import { l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-1VuiLaaR.mjs";
import { u as asPositiveFiniteNumber } from "./number-coercion-CkhMiRw8.mjs";
import { t as isAbortError } from "./abort-signal-QqAmLWTl.mjs";
import { t as formatErrorMessage } from "./errors-BvOkmQM5.mjs";
import { t as createSubsystemLogger } from "./subsystem-4NzR43uz.mjs";
import { t as SessionTranscriptReadFenceError } from "./session-transcript-read-fence-error-DoYPfzaJ.mjs";
import { t as createLazyImportLoader } from "./lazy-promise-DGqyc4Y4.mjs";
import { r as isIncognitoSessionKey } from "./session-key-CmZ4o9-l.mjs";
import { l as resolveAgentIdFromSessionKey, s as isUnscopedSessionKeySentinel } from "./session-key-DY3MOX4N.mjs";
import { c as resolveSessionStorePathCore } from "./paths-Bonddxfk.mjs";
import { r as normalizeProviderId } from "./provider-id-D1VImdKk.mjs";
import { g as resolveDefaultAgentId } from "./agent-scope-config-BEk6-ThS.mjs";
import { a as resolveMergedModelProviderConfig, r as findConfiguredProviderModel } from "./model-provider-config-BVE2xsBm.mjs";
import { s as normalizeStaticProviderModelId } from "./model-ref-shared-Df4xc5Gg.mjs";
import { b as registerAgentRunContext, o as clearAgentRunContext } from "./agent-run-registry-Cm8FlLIi.mjs";
import { n as findModelInCatalog } from "./model-catalog-lookup-_nlJdlgO.mjs";
import { i as resolveModelExtraParamSources } from "./model-extra-params-BN1mxasE.mjs";
import { c as resolveContextConfigProviderForRuntime } from "./openai-routing-DNTQ-lG2.mjs";
import { r as logVerbose } from "./globals-yEiTitH8.mjs";
import { d as resolveMaxActiveTranscriptBytes, u as refreshTranscriptByteCompactionLatch } from "./registry-BSFHwbcu.mjs";
import { m as isRenderablePayload } from "./reply-payload-BEgsL2xJ.mjs";
import { h as resolveSessionPinnedHarnessId } from "./agent-harness-session-key-Dx0vv6oG.mjs";
import { a as resolveCliBackendConfig } from "./cli-backends-CMl10xFW.mjs";
import { i as isCliRuntimeAliasForProvider } from "./model-runtime-aliases-B9nh73GM.mjs";
import { i as resolveSessionRuntimeOverrideForProvider, r as resolvePersistedSessionRuntimeId } from "./session-runtime-compat-ro9WhJ4w.mjs";
import { o as resolveEffectiveAgentRuntime } from "./thinking-runtime-CveqpPq0.mjs";
import "./model-selection-Cpoq0B2R.mjs";
import { t as isCliProvider } from "./model-selection-cli-46qX0ujd.mjs";
import { l as isMemoryFlushPlanNativeProviderOwned } from "./memory-state-YBTzZa6s.mjs";
import { h as resolveSessionStorePathForScope } from "./session-transcript-worker-runtime-BdmdicNg.mjs";
import "./session-transcript-read-fence-DqVaDIch.mjs";
import { o as resolveFreshSessionTotalTokens } from "./types-BGDhC4_W.mjs";
import { d as persistCompactionBoundaryWithSessionEntryAsync } from "./session-accessor-C3ljJ974.mjs";
import { l as updateSessionEntry } from "./session-accessor.entry-mutation-telsi3Ig.mjs";
import { n as acknowledgeReplySessionTransition } from "./reply-run-registry.state-BgHFgrrj.mjs";
import "./lanes-D7a4ntDu.mjs";
import { t as formatTokenCount } from "./token-format-ldfKpYv7.mjs";
import "./sessions-CRUJeu5H.mjs";
import { r as resolveSandboxConfigForAgent } from "./config-CqeBZkfZ.mjs";
import { i as withSandboxRuntimeStatusInWorker } from "./runtime-status-BBzhhE6k.mjs";
import { s as isBenignCompactionSkipResult } from "./request-error-facts-CtJZTTS5.mjs";
import { n as truncateUtf16WithEllipsis } from "./text-truncate-DrDnz8rI.mjs";
import { c as readSessionMessagesAsync, p as readSessionTranscriptAccountingAsync } from "./session-transcript-readers-Bka5K3vB.mjs";
import { n as MemoryFlushToolsUnavailableError } from "./core-coding-tools-DFJcX7yX.mjs";
import { _ as startFollowupRunPreAdoptionHeartbeat, u as refreshQueuedFollowupSession } from "./state-Bzhk4z8e.mjs";
import { p as resolveFollowupAbortSignal } from "./drain-C06t24a8.mjs";
import "./queue-DoAEwH02.mjs";
import { p as appendPostCompactionRefreshPrompt, y as createDeferredEmbeddedRunLifecycleManager } from "./builtin-openclaw-BxzDR6yL.mjs";
import { o as resolveBootstrapWarningSignaturesSeen } from "./bootstrap-budget-y7OLz5cL.mjs";
import "./sandbox-GCAKkjF5.mjs";
import { r as createToolResultPromptProjectionState } from "./session-prompt-state-BkfEGfU5.mjs";
import { L as estimateMessagesTokens } from "./settings-manager-2KjnbEXR.mjs";
import { t as resolveEffectiveCompactionReserveTokens } from "./agent-compaction-constants-DmXQuPyL.mjs";
import { t as SessionManager } from "./session-manager-BpvVpTVC.mjs";
import { n as incrementCompactionCount } from "./session-updates-DB8VygKs.mjs";
import { t as resolveContextTokens } from "./model-selection-context-C-FNaZM4.mjs";
import { t as createSessionMaintenanceFollowup } from "./run-C50ZeOtw.mjs";
import { t as runEmbeddedAgentEntry } from "./run-entry-BnMGfzuI.mjs";
import { t as emitAgentRunStatusEvent } from "./agent-run-status-events-D5G0IaGl.mjs";
import { h as buildRunEntrySelection, l as resolveRunThinkingLevelForFallbackCandidate, t as buildEmbeddedRunExecutionParams } from "./agent-runner-utils-CMtTx2u1.mjs";
import { n as memoryFlushResultIsSilent, r as resolveMemoryFlushPlanForRun, t as isToolsMemoryFlushPlan } from "./memory-flush-plan-DJiPOwMd.mjs";
import crypto from "node:crypto";
import { resolveOpenAIResponsesServerCompactionPlan } from "@openclaw/ai/internal/openai-responses-payload-policy";
import { resolveAnthropicServerCompactionPlan } from "@openclaw/ai/internal/anthropic";
//#region src/auto-reply/reply/agent-runner-memory-transcript-context.ts
async function readPreflightTranscriptContextMessages(scope, signal) {
	const readLegacyProjection = async () => {
		signal?.throwIfAborted();
		const messages = await readSessionMessagesAsync(scope, {
			mode: "full",
			reason: "preflight-compaction-estimate-legacy"
		});
		signal?.throwIfAborted();
		return messages.filter((message) => !("excludeFromContext" in message && message.excludeFromContext === true));
	};
	if (!scope.storePath || !scope.sessionKey) return await readLegacyProjection();
	const target = {
		...scope,
		sessionKey: scope.sessionKey,
		storePath: scope.storePath
	};
	for (let attempt = 0; attempt < 2; attempt += 1) try {
		const context = await SessionManager.openModelContextAsync(target, { signal });
		const messages = context.buildSessionContext().messages;
		if (messages.length > 0 || context.getEntries().length > 0) return messages;
		return await readLegacyProjection();
	} catch (error) {
		if (error instanceof SessionTranscriptReadFenceError && attempt === 0) continue;
		if (!(error instanceof Error) || error.message !== "Persisted legacy session transcripts require doctor/import migration before runtime use") throw error;
		return await readLegacyProjection();
	}
	throw new Error("Preflight transcript context retry exhausted");
}
async function readSessionLogSnapshot(params) {
	params.abortSignal?.throwIfAborted();
	const agentId = params.agentId ?? resolveAgentIdFromSessionKey(params.sessionKey);
	if (!params.sessionId || !params.storePath || !agentId) return params.includeTurnTaint ? { turnTainted: true } : {};
	const scope = {
		agentId,
		sessionId: params.sessionId,
		...params.sessionKey ? { sessionKey: params.sessionKey } : {},
		storePath: params.storePath
	};
	try {
		const snapshot = await readSessionTranscriptAccountingAsync(scope, {
			includeByteSize: params.includeByteSize,
			includeTurnTaint: params.includeTurnTaint,
			includeUsage: params.includeUsage,
			usageEventLimit: params.usageEventLimit
		}, params.abortSignal);
		params.abortSignal?.throwIfAborted();
		return snapshot;
	} catch {
		params.abortSignal?.throwIfAborted();
		return params.includeTurnTaint ? { turnTainted: true } : {};
	}
}
//#endregion
//#region src/auto-reply/reply/memory-flush-errors.ts
const MAX_FLUSH_ERROR_LENGTH = 200;
function resolveVisibleMemoryFlushErrorPayloads(payloads) {
	return (payloads ?? []).filter((payload) => payload.isError === true && isRenderablePayload(payload));
}
function buildVisibleMemoryFlushFailure(payloads) {
	const message = payloads.map((payload) => normalizeOptionalString(payload.text)).filter((text) => Boolean(text)).join("\n");
	return new Error(message || "Memory flush returned an error response");
}
function truncateMemoryFlushErrorMessage(err) {
	const message = normalizeOptionalString(formatErrorMessage(err)) || String(err);
	return truncateUtf16WithEllipsis(message, MAX_FLUSH_ERROR_LENGTH);
}
//#endregion
//#region src/auto-reply/reply/memory-flush.ts
function resolveEffectivePromptTokens(basePromptTokens, lastOutputTokens, promptTokenEstimate) {
	const base = Math.max(0, basePromptTokens ?? 0);
	const output = Math.max(0, lastOutputTokens ?? 0);
	const estimate = Math.max(0, promptTokenEstimate ?? 0);
	return base + output + estimate;
}
function estimatePromptTokensForMemoryFlush(prompt) {
	const trimmed = normalizeOptionalString(prompt);
	if (!trimmed) return;
	const tokens = asPositiveFiniteNumber(estimateMessagesTokens([{
		role: "user",
		content: trimmed,
		timestamp: Date.now()
	}]));
	return tokens === void 0 ? void 0 : Math.ceil(tokens);
}
function resolveCompactionThreshold(params) {
	const contextWindow = Math.max(1, Math.floor(params.contextWindowTokens));
	const reserveTokens = Math.max(0, Math.floor(params.reserveTokensFloor));
	return Math.max(0, contextWindow - reserveTokens, Math.floor(params.minimumThresholdTokens ?? 0));
}
function resolveResponsesServerCompactionThreshold(params) {
	const provider = params.provider?.trim();
	const modelId = params.modelId?.trim();
	if (!provider || !modelId) return;
	const normalizedProvider = normalizeProviderId(provider);
	const normalizeModelId = (value) => normalizeStaticProviderModelId(normalizedProvider, value).trim().toLowerCase();
	const providerConfig = resolveMergedModelProviderConfig(params.cfg, provider);
	const configuredModel = findConfiguredProviderModel(providerConfig, provider, modelId, normalizeModelId);
	const { defaultParams, modelParams } = resolveModelExtraParamSources({
		config: params.cfg,
		provider,
		modelId
	});
	const extraParams = {
		...defaultParams,
		...modelParams
	};
	const compactionModel = {
		provider,
		api: configuredModel?.api ?? providerConfig?.api,
		baseUrl: configuredModel?.baseUrl ?? providerConfig?.baseUrl,
		contextWindow: configuredModel?.contextWindow ?? params.contextWindowTokens
	};
	if (normalizedProvider === "anthropic") return resolveAnthropicServerCompactionPlan({
		...compactionModel,
		api: compactionModel.api ?? "anthropic-messages"
	}, extraParams).threshold;
	return resolveOpenAIResponsesServerCompactionPlan({
		...compactionModel,
		api: compactionModel.api ?? (normalizedProvider === "openai" ? "openai-responses" : void 0),
		baseUrl: compactionModel.baseUrl ?? (normalizedProvider === "openai" ? "https://api.openai.com/v1" : void 0),
		compat: configuredModel?.compat,
		contextTokens: configuredModel?.contextTokens ?? params.contextWindowTokens
	}, extraParams).threshold;
}
function shouldRunMemoryFlush(params) {
	return Boolean(shouldRunPreflightCompaction(params) && params.entry && !hasAlreadyFlushedForCurrentCompaction(params.entry));
}
function shouldRunPreflightCompaction(params) {
	if (!params.entry) return false;
	const projectedTokens = asPositiveFiniteNumber(params.tokenCount);
	const totalTokens = projectedTokens === void 0 ? resolveFreshSessionTotalTokens(params.entry) : Math.floor(projectedTokens);
	return typeof totalTokens === "number" && totalTokens > 0 && params.threshold > 0 && totalTokens >= params.threshold;
}
/** One flush per compaction cycle, regardless of token or transcript-size trigger. */
function hasAlreadyFlushedForCurrentCompaction(entry) {
	const compactionCount = entry.compactionCount ?? 0;
	const lastFlushAt = entry.memoryFlush?.compactionCount;
	return typeof lastFlushAt === "number" && lastFlushAt === compactionCount;
}
//#endregion
//#region src/auto-reply/reply/agent-runner-memory.ts
const MAX_FLUSH_FAILURES = 3;
const preflightCompactionLog = createSubsystemLogger("auto-reply/preflight-compaction");
const memoryFlushLog = createSubsystemLogger("auto-reply/memory-flush");
const embeddedAgentRuntimeLoader = createLazyImportLoader(() => import("./embedded-agent-WpG0US1O.mjs"));
const memoryFlushPreparationLoader = createLazyImportLoader(() => import("./memory-flush-prepare-C_XZEwMD.mjs"));
const toolResultTruncationRuntimeLoader = createLazyImportLoader(() => import("./tool-result-truncation-BKSzBNuQ.mjs"));
function followupUsesCliRuntime(params, runtimeId) {
	const provider = params.followupRun.run.provider;
	if (params.agentHarnessId) return isCliRuntimeAliasForProvider({
		provider,
		runtime: params.agentHarnessId,
		cfg: params.cfg
	});
	if (isCliProvider(provider, params.cfg)) return true;
	return [resolvePersistedSessionRuntimeId(params.sessionEntry), runtimeId].some((runtime) => isCliRuntimeAliasForProvider({
		provider,
		runtime,
		cfg: params.cfg
	}));
}
function resolveFollowupAgentRuntimeId(params) {
	if (params.agentHarnessId) return params.agentHarnessId;
	const matchingSessionEntry = params.sessionEntry?.sessionId === params.followupRun.run.sessionId ? params.sessionEntry : void 0;
	return resolveEffectiveAgentRuntime({
		cfg: params.cfg,
		provider: params.followupRun.run.provider,
		modelId: params.followupRun.run.model,
		agentId: params.followupRun.run.agentId ?? resolveDefaultAgentId(params.cfg),
		sessionKey: params.sessionKey ?? params.followupRun.run.sessionKey,
		sessionEntry: matchingSessionEntry
	});
}
function followupOwnsNativeCompaction(params, runtimeId) {
	return resolveCliBackendConfig(runtimeId, params.cfg, { agentId: params.followupRun.run.agentId })?.ownsNativeCompaction === true;
}
function resolveFollowupContextTokens({ cfg, followupRun, defaultModel }, runtimeId) {
	const { provider } = followupRun.run;
	const model = followupRun.run.model ?? defaultModel;
	const catalogModel = findModelInCatalog(followupRun.run.thinkingCatalog ?? [], provider, model);
	return resolveContextTokens({
		cfg,
		provider: resolveContextConfigProviderForRuntime({
			provider,
			runtimeId,
			config: cfg
		}),
		model,
		modelContextWindow: catalogModel?.contextWindow,
		modelContextTokens: catalogModel?.contextTokens
	});
}
function hasUsableProviderPromptUsage(usage) {
	return typeof usage?.promptTokens === "number" && Number.isFinite(usage.promptTokens) && usage.promptTokens > 0;
}
const TRANSCRIPT_OUTPUT_READ_BUFFER_TOKENS = 8192;
async function estimateProviderPromptTokens(messages, contextWindowTokens, priorPromptTokens = 0) {
	if (messages.length === 0) return Math.ceil(priorPromptTokens);
	const { truncateOversizedToolResultsInMessages } = await toolResultTruncationRuntimeLoader.load();
	const projected = truncateOversizedToolResultsInMessages(messages, contextWindowTokens, void 0, void 0, createToolResultPromptProjectionState()).messages;
	const tokens = estimateMessagesTokens(projected);
	return Number.isFinite(tokens) && tokens >= 0 ? Math.ceil(priorPromptTokens) + Math.ceil(tokens) : void 0;
}
async function estimatePromptTokensFromSessionTranscript({ abortSignal, ...params }) {
	const sessionId = normalizeOptionalString(params.sessionId);
	if (!sessionId) return;
	try {
		const snapshot = await readSessionLogSnapshot({
			agentId: params.agentId,
			sessionId,
			sessionKey: params.sessionKey,
			storePath: params.storePath,
			includeByteSize: true,
			includeUsage: true,
			abortSignal
		});
		let usage = snapshot.usage;
		if (!hasUsableProviderPromptUsage(usage) && typeof snapshot.eventCount === "number" && snapshot.eventCount > 512) usage = (await readSessionLogSnapshot({
			agentId: params.agentId,
			sessionId,
			sessionKey: params.sessionKey,
			storePath: params.storePath,
			includeByteSize: false,
			includeUsage: true,
			usageEventLimit: snapshot.eventCount,
			abortSignal
		})).usage;
		const normalizedOutputTokens = usage?.outputTokens === void 0 ? void 0 : Math.ceil(usage.outputTokens);
		const providerUsage = hasUsableProviderPromptUsage(usage) ? usage : void 0;
		const messages = providerUsage ? providerUsage.trailingMessages : await readPreflightTranscriptContextMessages({
			...params,
			sessionId
		}, abortSignal);
		const promptTokens = await estimateProviderPromptTokens(messages, params.contextWindowTokens, providerUsage?.promptTokens);
		if (promptTokens === void 0) return;
		return {
			promptTokens,
			promptTokenSource: providerUsage ? messages.length > 0 ? "provider_usage_plus_prompt_projection" : "provider_usage" : "prompt_projection",
			...!providerUsage ? { promptIncludesOutput: true } : {},
			outputTokens: normalizedOutputTokens,
			transcriptByteSize: snapshot.byteSize
		};
	} catch (error) {
		abortSignal?.throwIfAborted();
		return error instanceof SessionTranscriptReadFenceError ? Promise.reject(error) : void 0;
	}
}
/** Compacts session context before a reply or after a completed direct command. */
async function runSessionCompactionIfNeeded(params) {
	const operatorAuthority = params.followupRun.operatorAuthority;
	const assertActive = () => {
		params.abortSignal?.throwIfAborted();
		operatorAuthority?.assertCurrent();
		if (params.authorize?.() === false) throw new Error("Session compaction maintenance is no longer active");
	};
	if (!params.sessionKey) return params.sessionEntry;
	let entry = params.sessionEntry ?? params.sessionStore?.[params.sessionKey];
	if (!entry?.sessionId) return entry;
	const runtimeParams = {
		...params,
		sessionEntry: entry
	};
	assertActive();
	const runtimeId = resolveFollowupAgentRuntimeId(runtimeParams);
	const isCli = followupUsesCliRuntime(runtimeParams, runtimeId);
	const ownsNativeCompaction = followupOwnsNativeCompaction(runtimeParams, runtimeId);
	if (isCli || ownsNativeCompaction) return entry;
	const isCodexRuntime = normalizeLowercaseStringOrEmpty(runtimeId) === "codex";
	const compactionSessionKey = params.sessionKey;
	const configuredAgentId = params.followupRun.run.agentId ?? resolveDefaultAgentId(params.cfg);
	const compactionAgentId = isUnscopedSessionKeySentinel(compactionSessionKey) ? configuredAgentId : resolveAgentIdFromSessionKey(compactionSessionKey, configuredAgentId);
	const compactionStorePath = resolveSessionStorePathForScope({
		agentId: compactionAgentId,
		sessionKey: compactionSessionKey,
		storePath: params.storePath ?? resolveSessionStorePathCore(params.cfg.session?.store, { agentId: compactionAgentId })
	});
	const compactionStore = params.sessionStore ?? { [compactionSessionKey]: entry };
	const compactionTarget = {
		agentId: compactionAgentId,
		sessionKey: compactionSessionKey,
		storePath: compactionStorePath
	};
	const readTranscriptSize = (sessionId) => readSessionLogSnapshot({
		...compactionTarget,
		sessionId,
		includeByteSize: true,
		includeUsage: false,
		abortSignal: params.abortSignal
	});
	const contextWindowTokens = resolveFollowupContextTokens(params, runtimeId);
	const reserveTokensFloor = (resolveMemoryFlushPlanForRun({
		cfg: params.cfg,
		contextWindowTokens
	})?.plan)?.reserveTokensFloor ?? resolveEffectiveCompactionReserveTokens({
		contextTokenBudget: contextWindowTokens,
		reserveTokens: 2e4
	});
	const freshPersistedTokens = resolveFreshSessionTotalTokens(entry);
	const promptTokenEstimate = estimatePromptTokensForMemoryFlush(params.promptForEstimate ?? params.followupRun.prompt);
	const responsesServerCompactionThreshold = resolveResponsesServerCompactionThreshold({
		contextWindowTokens,
		cfg: params.cfg,
		provider: params.followupRun.run.provider,
		modelId: params.followupRun.run.model ?? params.defaultModel
	});
	const threshold = resolveCompactionThreshold({
		contextWindowTokens,
		reserveTokensFloor,
		minimumThresholdTokens: responsesServerCompactionThreshold
	});
	const freshNeedsOutputRead = typeof freshPersistedTokens === "number" && typeof promptTokenEstimate === "number" && threshold > 0 && freshPersistedTokens + promptTokenEstimate >= threshold - TRANSCRIPT_OUTPUT_READ_BUFFER_TOKENS;
	const maxActiveTranscriptBytes = resolveMaxActiveTranscriptBytes(params.cfg);
	const shouldCheckActiveTranscriptBytes = typeof maxActiveTranscriptBytes === "number";
	const transcriptUsageTokens = params.isHeartbeat || isCodexRuntime || typeof freshPersistedTokens === "number" && !freshNeedsOutputRead ? void 0 : await estimatePromptTokensFromSessionTranscript({
		...compactionTarget,
		abortSignal: params.abortSignal,
		sessionId: entry.sessionId,
		contextWindowTokens
	});
	const transcriptSizeSnapshot = shouldCheckActiveTranscriptBytes && transcriptUsageTokens?.transcriptByteSize === void 0 ? await readTranscriptSize(entry.sessionId) : void 0;
	assertActive();
	const activeTranscriptBytes = transcriptUsageTokens?.transcriptByteSize ?? transcriptSizeSnapshot?.byteSize;
	const exceedsTranscriptByteThreshold = typeof activeTranscriptBytes === "number" && typeof maxActiveTranscriptBytes === "number" && activeTranscriptBytes >= maxActiveTranscriptBytes;
	let terminalCompactionNoticeSent = false;
	const notifyCompaction = async (phase, text) => {
		terminalCompactionNoticeSent = phase !== "start";
		try {
			await params.onCompactionNotice?.(phase, text);
		} catch (err) {
			logVerbose(`preflightCompaction notice delivery failed: ${String(err)}`);
		}
	};
	const latch = entry.transcriptByteCompactionLatch;
	const refreshedTranscriptByteCompactionLatch = refreshTranscriptByteCompactionLatch(latch, entry.sessionId, maxActiveTranscriptBytes, activeTranscriptBytes);
	const transcriptByteCompactionLatched = exceedsTranscriptByteThreshold && refreshedTranscriptByteCompactionLatch !== void 0;
	if (refreshedTranscriptByteCompactionLatch !== latch) {
		const compactionCount = await incrementCompactionCount({
			...compactionTarget,
			amount: 0,
			expectedSession: entry,
			sessionStore: compactionStore,
			transcriptByteCompactionLatch: refreshedTranscriptByteCompactionLatch ?? null
		});
		assertActive();
		if (compactionCount === void 0) throw new Error("Session changed before byte-compaction progress could be cleared");
		entry = compactionStore[compactionSessionKey] ?? entry;
	}
	const shouldCompactByTranscriptBytes = exceedsTranscriptByteThreshold && !transcriptByteCompactionLatched;
	if (transcriptByteCompactionLatched) {
		await notifyCompaction("context_bounded");
		assertActive();
	}
	if (isCodexRuntime && !shouldCompactByTranscriptBytes) {
		logVerbose(`preflightCompaction skipped: sessionKey=${params.sessionKey} runtime=codex reason=codex_native_auto_compaction activeTranscriptBytes=${activeTranscriptBytes ?? "undefined"} maxActiveTranscriptBytes=${maxActiveTranscriptBytes ?? "undefined"}`);
		return entry;
	}
	const transcriptPromptTokens = transcriptUsageTokens?.promptTokens;
	const transcriptOutputTokens = transcriptUsageTokens?.outputTokens;
	const transcriptEstimateOutputTokens = transcriptUsageTokens?.promptIncludesOutput ? void 0 : transcriptOutputTokens;
	const usageProjectedTokenCount = typeof transcriptPromptTokens === "number" ? resolveEffectivePromptTokens(transcriptPromptTokens, transcriptEstimateOutputTokens, promptTokenEstimate) : void 0;
	const freshProjectedTokenCount = typeof freshPersistedTokens === "number" ? resolveEffectivePromptTokens(freshPersistedTokens, transcriptOutputTokens, promptTokenEstimate) : void 0;
	const tokenCountForCompaction = asPositiveFiniteNumber(Math.max(usageProjectedTokenCount ?? 0, freshProjectedTokenCount ?? 0));
	logVerbose(`preflightCompaction check: sessionKey=${params.sessionKey} tokenCount=${tokenCountForCompaction ?? freshPersistedTokens ?? "undefined"} contextWindow=${contextWindowTokens} threshold=${threshold} responsesServerCompactionThreshold=${responsesServerCompactionThreshold ?? "undefined"} isHeartbeat=${params.isHeartbeat} isCli=${isCli} persistedFresh=${entry?.totalTokensFresh === true} transcriptPromptTokens=${transcriptPromptTokens ?? "undefined"} transcriptPromptSource=${transcriptUsageTokens?.promptTokenSource ?? "undefined"} promptTokensEst=${promptTokenEstimate ?? "undefined"} activeTranscriptBytes=${activeTranscriptBytes ?? "undefined"} maxActiveTranscriptBytes=${maxActiveTranscriptBytes ?? "undefined"} sizeTrigger=${shouldCompactByTranscriptBytes} sizeTriggerLatched=${transcriptByteCompactionLatched}`);
	if (!(!params.isHeartbeat && shouldRunPreflightCompaction({
		entry,
		tokenCount: tokenCountForCompaction,
		threshold
	})) && !shouldCompactByTranscriptBytes) return entry;
	if (params.beforeCompaction) {
		const refreshed = await params.beforeCompaction(entry);
		assertActive();
		return runSessionCompactionIfNeeded({
			...params,
			sessionEntry: refreshed,
			beforeCompaction: void 0
		});
	}
	const compactionTrigger = shouldCompactByTranscriptBytes ? "transcript_bytes" : "tokens";
	logVerbose(`preflightCompaction triggered: sessionKey=${params.sessionKey} tokenCount=${tokenCountForCompaction ?? freshPersistedTokens ?? "undefined"} threshold=${threshold} trigger=${compactionTrigger} activeTranscriptBytes=${activeTranscriptBytes ?? "undefined"} maxActiveTranscriptBytes=${maxActiveTranscriptBytes ?? "undefined"}`);
	assertActive();
	params.onCompactionStart?.();
	let expectedSession = entry;
	let admissionTransition;
	let hostAccountingCommitted = false;
	const recordCompactionAccounting = async (acceptedEntry, tokensAfter, compactionKind, amount = 1) => {
		const postCompactionBytes = exceedsTranscriptByteThreshold ? (await readTranscriptSize(acceptedEntry.sessionId)).byteSize : void 0;
		assertActive();
		const transcriptByteCompactionLatch = typeof postCompactionBytes === "number" && typeof maxActiveTranscriptBytes === "number" && postCompactionBytes >= maxActiveTranscriptBytes ? {
			activeBytes: postCompactionBytes,
			sessionId: acceptedEntry.sessionId,
			maxBytes: maxActiveTranscriptBytes
		} : void 0;
		if (await incrementCompactionCount({
			...compactionTarget,
			sessionStore: compactionStore,
			amount,
			tokensAfter,
			compactionKind,
			expectedSession: acceptedEntry,
			transcriptByteCompactionLatch: transcriptByteCompactionLatch ?? null,
			authorize: () => {
				assertActive();
				return true;
			}
		}) === void 0) throw new Error("Session changed before compaction maintenance could be recorded");
	};
	const stopHeartbeat = startFollowupRunPreAdoptionHeartbeat(params.followupRun.turnAdoptionLifecycle, params.abortSignal);
	try {
		await notifyCompaction("start");
		assertActive();
		const result = await (await embeddedAgentRuntimeLoader.load()).compactEmbeddedAgentSession({
			sessionId: entry.sessionId,
			sessionKey: compactionSessionKey,
			sessionTarget: {
				...compactionTarget,
				sessionId: entry.sessionId
			},
			sandboxSessionKey: params.runtimePolicySessionKey,
			allowGatewaySubagentBinding: true,
			messageChannel: params.followupRun.run.messageProvider,
			clientCaps: params.followupRun.run.clientCaps,
			conversationToolPolicy: params.followupRun.run.conversationToolPolicy,
			groupId: entry.groupId ?? params.followupRun.run.groupId,
			groupChannel: entry.groupChannel ?? params.followupRun.run.groupChannel,
			groupSpace: entry.space ?? params.followupRun.run.groupSpace,
			senderId: params.followupRun.run.senderId,
			senderName: params.followupRun.run.senderName,
			senderUsername: params.followupRun.run.senderUsername,
			senderE164: params.followupRun.run.senderE164,
			inputProvenance: params.followupRun.run.inputProvenance,
			sessionFile: compactionSessionKey,
			workspaceDir: params.followupRun.run.workspaceDir,
			cwd: params.followupRun.run.cwd,
			agentDir: params.followupRun.run.agentDir,
			config: params.cfg,
			agentAccountId: params.followupRun.run.agentAccountId,
			conversationRoutePeerId: params.followupRun.run.conversationRoutePeerId,
			chatType: params.followupRun.run.chatType,
			skillsSnapshot: entry.skillsSnapshot ?? params.followupRun.run.skillsSnapshot,
			provider: params.followupRun.run.provider,
			model: params.followupRun.run.model,
			authProfileId: params.followupRun.run.authProfileId,
			authProfileIdSource: params.followupRun.run.authProfileIdSource,
			sessionEntry: entry,
			agentHarnessId: params.agentHarnessId ?? (entry.sessionId === params.followupRun.run.sessionId ? entry.modelSelectionLocked === true ? resolvePersistedSessionRuntimeId(entry) : runtimeId : void 0),
			modelSelectionLocked: entry.modelSelectionLocked === true,
			thinkLevel: params.followupRun.run.thinkLevel,
			bashElevated: params.followupRun.run.bashElevated,
			trigger: "budget",
			force: true,
			forcePreflight: true,
			preflightRequired: true,
			preflightCompactionTrigger: compactionTrigger,
			deferOwningContextEngineCompaction: false,
			contextTokenBudget: contextWindowTokens,
			currentTokenCount: tokenCountForCompaction ?? freshPersistedTokens,
			ownerNumbers: params.followupRun.run.ownerNumbers,
			abortSignal: params.abortSignal
		}, {
			assertActive,
			sourceAuthority: {
				assertActive,
				operatorAuthority
			},
			requestBudget: params.compactionRequestBudget,
			pendingUserEntryId: params.pendingUserEntryId,
			...compactionTrigger === "transcript_bytes" && isCodexRuntime ? {
				transcriptBytePreflightHarness: "codex",
				...compactionTarget.storePath && typeof activeTranscriptBytes === "number" && typeof maxActiveTranscriptBytes === "number" ? { withCompactionPersistenceAsync: async (prepared) => {
					const committed = await persistCompactionBoundaryWithSessionEntryAsync({
						...compactionTarget,
						expectedLifecycleRevision: expectedSession.lifecycleRevision,
						expectedWriterRunId: expectedSession.activeWriterRunId,
						sessionId: expectedSession.sessionId
					}, {
						prepared,
						transcriptByteCompactionLatch: {
							activeBytes: activeTranscriptBytes,
							sessionId: expectedSession.sessionId,
							maxBytes: maxActiveTranscriptBytes
						}
					}, assertActive);
					hostAccountingCommitted = true;
					return committed;
				} } : {},
				onHostCompactionTranscriptSettled: async (commit) => {
					await recordCompactionAccounting(commit.entry, void 0, void 0, 0);
				}
			} : {},
			onHostCompactionCommitted: async (commit) => {
				await recordCompactionAccounting(commit.entry, commit.tokensAfter, commit.compactionKind, hostAccountingCommitted ? 0 : 1);
				hostAccountingCommitted = true;
			},
			onCommitted: (accepted) => {
				admissionTransition = accepted.admissionTransition;
				expectedSession = accepted.entry;
				entry = accepted.entry;
				compactionStore[compactionSessionKey] = accepted.entry;
				params.onCompactionCommitted?.(accepted);
			}
		});
		if (!result?.ok || !result.compacted) {
			assertActive();
			const reason = (result?.ok ? normalizeOptionalString(result.reason) : result?.reason) ?? "not_compacted";
			if (!exceedsTranscriptByteThreshold && result && isBenignCompactionSkipResult(result)) {
				await notifyCompaction("skipped");
				logVerbose(`preflightCompaction skipped: sessionKey=${params.sessionKey} reason=${reason}`);
				return entry;
			}
			preflightCompactionLog.warn(`preflight compaction failed: ${reason}`);
			if (exceedsTranscriptByteThreshold) {
				await recordCompactionAccounting(expectedSession, void 0, void 0, 0);
				assertActive();
				await notifyCompaction("context_bounded");
				return compactionStore[compactionSessionKey] ?? entry;
			}
			await notifyCompaction("incomplete");
			throw new Error(`Preflight compaction required but failed: ${reason}`);
		}
		if (params.replyOperation && admissionTransition) {
			await acknowledgeReplySessionTransition(params.replyOperation, admissionTransition);
			assertActive();
		}
		if (!hostAccountingCommitted) await recordCompactionAccounting(expectedSession, result.result?.tokensAfter, result.compactionKind);
		assertActive();
		entry = compactionStore[compactionSessionKey] ?? entry;
		const transcriptByteCompactionLatch = entry.transcriptByteCompactionLatch;
		if (transcriptByteCompactionLatch) preflightCompactionLog.warn("byte-triggered compaction left oversized history; continuing with bounded context", {
			sessionKey: compactionSessionKey,
			activeTranscriptBytes: transcriptByteCompactionLatch.activeBytes,
			maxActiveTranscriptBytes: transcriptByteCompactionLatch.maxBytes
		});
		await appendPostCompactionRefreshPrompt({
			cfg: params.cfg,
			followupRun: params.followupRun
		});
		assertActive();
		const serverNotice = result.compactionKind === "server-endpoint" && typeof result.result?.tokensBefore === "number" && typeof result.result.tokensAfter === "number" ? `🧹 Server-side compaction complete (${formatTokenCount(result.result.tokensBefore)} → ${formatTokenCount(result.result.tokensAfter)})` : void 0;
		await notifyCompaction(transcriptByteCompactionLatch ? "context_bounded" : "end", transcriptByteCompactionLatch ? void 0 : serverNotice);
		assertActive();
		entry = compactionStore[compactionSessionKey] ?? entry;
		const previousSessionId = params.followupRun.run.sessionId;
		params.followupRun.run.sessionId = entry.sessionId;
		params.onSessionIdChanged?.(entry.sessionId);
		const queueKey = params.followupRun.run.sessionKey ?? params.sessionKey;
		if (queueKey) {
			params.followupRun.run.sessionFile = queueKey;
			refreshQueuedFollowupSession({
				key: queueKey,
				previousSessionId,
				nextSessionId: entry.sessionId,
				nextSessionFile: queueKey
			});
		}
		return entry;
	} catch (err) {
		if (!terminalCompactionNoticeSent && !params.abortSignal?.aborted) await notifyCompaction("incomplete");
		throw err;
	} finally {
		stopHeartbeat?.();
	}
}
/** Runs pre-compaction memory flush when transcript state warrants it. */
async function runMemoryFlushIfNeeded(params) {
	const abortSignal = resolveFollowupAbortSignal({
		abortSignal: params.replyOperation?.abortSignal ?? params.abortSignal,
		operatorAuthority: params.followupRun.operatorAuthority
	});
	const assertMemoryFlushCurrent = () => {
		abortSignal?.throwIfAborted();
		params.followupRun.operatorAuthority?.assertCurrent();
	};
	const memoryFlushWritable = !params.sessionKey || await withSandboxRuntimeStatusInWorker({
		cfg: params.cfg,
		agentId: params.followupRun.run.agentId,
		sessionKey: params.sessionKey,
		classificationSessionKey: params.runtimePolicySessionKey
	}, {
		env: process.env,
		cwd: process.cwd(),
		assertCurrent: assertMemoryFlushCurrent
	}, async ({ sandboxed, workspaceAccess: access, classificationAgentId: agentId }) => !sandboxed || (access ?? resolveSandboxConfigForAgent(params.cfg, agentId).workspaceAccess) === "rw");
	let entry = params.sessionEntry ?? (params.sessionKey ? params.sessionStore?.[params.sessionKey] : void 0);
	if (entry?.incognito === true || isIncognitoSessionKey(params.sessionKey)) return {
		sessionEntry: entry,
		outcome: "skipped"
	};
	const runtimeParams = {
		...params,
		sessionEntry: entry
	};
	const runtimeId = resolveFollowupAgentRuntimeId(runtimeParams);
	const isCli = followupUsesCliRuntime(runtimeParams, runtimeId) || followupOwnsNativeCompaction(runtimeParams, runtimeId);
	if (!((memoryFlushWritable || isMemoryFlushPlanNativeProviderOwned()) && !params.isHeartbeat && !isCli)) return {
		sessionEntry: entry,
		outcome: "skipped"
	};
	const flushRunId = crypto.randomUUID();
	let flushRunRegistered = false;
	const recordFailure = (error) => recordMemoryFlushFailure(error, params, entry);
	const contextWindowTokens = resolveFollowupContextTokens(params, runtimeId);
	let memoryFlushResolution;
	try {
		memoryFlushResolution = resolveMemoryFlushPlanForRun({
			cfg: params.cfg,
			contextWindowTokens
		});
	} catch (error) {
		return await recordFailure(error);
	}
	if (!memoryFlushResolution) return {
		sessionEntry: entry,
		outcome: "skipped"
	};
	const memoryFlushPlan = memoryFlushResolution.plan;
	if (!isToolsMemoryFlushPlan(memoryFlushPlan) && !memoryFlushWritable) return {
		sessionEntry: entry,
		outcome: "skipped"
	};
	const promptTokenEstimate = estimatePromptTokensForMemoryFlush(params.promptForEstimate ?? params.followupRun.prompt);
	const persistedPromptTokens = resolveFreshSessionTotalTokens(entry);
	const hasFreshPersistedPromptTokens = persistedPromptTokens !== void 0;
	const flushThreshold = Math.max(0, resolveCompactionThreshold({
		contextWindowTokens,
		reserveTokensFloor: memoryFlushPlan.reserveTokensFloor
	}) - Math.max(0, Math.floor(memoryFlushPlan.softThresholdTokens)));
	const shouldReadTranscriptForOutput = entry && hasFreshPersistedPromptTokens && typeof promptTokenEstimate === "number" && flushThreshold > 0 && persistedPromptTokens + promptTokenEstimate >= flushThreshold - TRANSCRIPT_OUTPUT_READ_BUFFER_TOKENS;
	const shouldReadTranscript = Boolean(entry && (!hasFreshPersistedPromptTokens || shouldReadTranscriptForOutput));
	const forceFlushTranscriptBytes = memoryFlushPlan.forceFlushTranscriptBytes;
	const shouldCheckTranscriptSizeForForcedFlush = Boolean(entry && Number.isFinite(forceFlushTranscriptBytes) && forceFlushTranscriptBytes > 0);
	const sessionLogSnapshot = entry ? await readSessionLogSnapshot({
		agentId: params.followupRun.run.agentId,
		sessionId: params.followupRun.run.sessionId,
		sessionKey: params.sessionKey ?? params.followupRun.run.sessionKey,
		storePath: params.storePath,
		includeByteSize: shouldCheckTranscriptSizeForForcedFlush,
		includeTurnTaint: true,
		includeUsage: shouldReadTranscript,
		abortSignal
	}) : void 0;
	assertMemoryFlushCurrent();
	const transcriptByteSize = sessionLogSnapshot?.byteSize;
	const shouldForceFlushByTranscriptSize = typeof transcriptByteSize === "number" && transcriptByteSize >= forceFlushTranscriptBytes;
	const transcriptUsageSnapshot = sessionLogSnapshot?.usage;
	const transcriptOutputTokens = transcriptUsageSnapshot?.outputTokens;
	const transcriptPromptTokens = hasUsableProviderPromptUsage(transcriptUsageSnapshot) ? await estimateProviderPromptTokens(transcriptUsageSnapshot.trailingMessages, contextWindowTokens, transcriptUsageSnapshot.promptTokens) : void 0;
	const shouldPersistTranscriptPromptTokens = transcriptPromptTokens !== void 0 && (persistedPromptTokens === void 0 || transcriptPromptTokens > persistedPromptTokens);
	assertMemoryFlushCurrent();
	if (entry && shouldPersistTranscriptPromptTokens) {
		const usageUpdate = {
			totalTokens: transcriptPromptTokens,
			totalTokensFresh: true,
			totalTokensVersion: 1
		};
		entry = {
			...entry,
			...usageUpdate
		};
		if (params.sessionKey && params.sessionStore) params.sessionStore[params.sessionKey] = entry;
		if (params.storePath && params.sessionKey) try {
			const updatedEntry = await updateSessionEntry({
				storePath: params.storePath,
				sessionKey: params.sessionKey
			}, () => usageUpdate, {
				skipMaintenance: true,
				takeCacheOwnership: true
			});
			if (updatedEntry) {
				entry = updatedEntry;
				if (params.sessionStore) params.sessionStore[params.sessionKey] = updatedEntry;
			}
		} catch (err) {
			logVerbose(`failed to persist derived prompt totalTokens: ${String(err)}`);
		}
	}
	const promptTokensSnapshot = Math.max(persistedPromptTokens ?? 0, transcriptPromptTokens ?? 0);
	const projectedTokenCount = promptTokensSnapshot > 0 ? resolveEffectivePromptTokens(promptTokensSnapshot, transcriptOutputTokens, promptTokenEstimate) : void 0;
	const tokenCountForFlush = asPositiveFiniteNumber(projectedTokenCount);
	logVerbose(`memoryFlush check: sessionKey=${params.sessionKey} tokenCount=${tokenCountForFlush ?? "undefined"} contextWindow=${contextWindowTokens} threshold=${flushThreshold} isHeartbeat=${params.isHeartbeat} isCli=${isCli} memoryFlushWritable=${memoryFlushWritable} compactionCount=${entry?.compactionCount ?? 0} memoryFlushCompactionCount=${entry?.memoryFlush?.compactionCount ?? "undefined"} persistedPromptTokens=${persistedPromptTokens ?? "undefined"} persistedFresh=${entry?.totalTokensFresh === true} promptTokensEst=${promptTokenEstimate ?? "undefined"} transcriptPromptTokens=${transcriptPromptTokens ?? "undefined"} transcriptOutputTokens=${transcriptOutputTokens ?? "undefined"} projectedTokenCount=${projectedTokenCount ?? "undefined"} transcriptBytes=${transcriptByteSize ?? "undefined"} forceFlushTranscriptBytes=${forceFlushTranscriptBytes} forceFlushByTranscriptSize=${shouldForceFlushByTranscriptSize}`);
	if (!(shouldRunMemoryFlush({
		entry,
		tokenCount: tokenCountForFlush,
		threshold: flushThreshold
	}) || shouldForceFlushByTranscriptSize && entry != null && !hasAlreadyFlushedForCurrentCompaction(entry))) return {
		sessionEntry: entry,
		outcome: "skipped"
	};
	logVerbose(`memoryFlush triggered: sessionKey=${params.sessionKey} tokenCount=${tokenCountForFlush ?? "undefined"} threshold=${flushThreshold}`);
	params.replyOperation?.setPhase("memory_flushing");
	let bootstrapPromptWarningSignaturesSeen = resolveBootstrapWarningSignaturesSeen(entry?.systemPromptReport ?? (params.sessionKey ? params.sessionStore?.[params.sessionKey]?.systemPromptReport : void 0));
	let persistenceToolCallSucceeded = false;
	let preparedAttempt;
	try {
		assertMemoryFlushCurrent();
		preparedAttempt = await (await memoryFlushPreparationLoader.load()).prepareMemoryFlushAttempt({
			...params,
			sessionEntry: entry,
			flushRunId,
			contextWindowTokens,
			memoryFlushWritable,
			abortSignal,
			assertCurrent: assertMemoryFlushCurrent,
			recordPersistenceToolSuccess: () => {
				persistenceToolCallSucceeded = true;
			}
		});
	} catch (error) {
		return await recordFailure(error);
	}
	if (!preparedAttempt) return {
		sessionEntry: entry,
		outcome: "skipped"
	};
	const { plan: activeMemoryFlushPlan, writePath: memoryFlushWritePath, systemPrompt: flushSystemPrompt, selection, preparedRunAdmission, memorySession, memoryAudience: flushMemoryAudience, memoryFlushTools } = preparedAttempt;
	const resolveRuntimePolicySessionKey = () => params.runtimePolicySessionKey ?? params.followupRun.run.runtimePolicySessionKey ?? params.sessionKey;
	const sourcePolicySessionKey = resolveRuntimePolicySessionKey() ?? params.followupRun.run.sessionKey;
	const maintenanceRun = createSessionMaintenanceFollowup({
		run: params.followupRun.run,
		sessionEntry: {
			sessionId: memorySession.sessionId,
			updatedAt: Date.now()
		},
		cfg: params.cfg,
		sessionKey: memorySession.sessionKey,
		runtimePolicySessionKey: sourcePolicySessionKey,
		provider: selection.provider,
		model: selection.model,
		auth: params.followupRun.run
	}).run;
	const deferredLifecycle = createDeferredEmbeddedRunLifecycleManager({
		runId: flushRunId,
		sessionId: memorySession.sessionId,
		sessionKey: memorySession.sessionKey,
		sessionFile: memorySession.sessionFile,
		abortSignal
	});
	const flushedCompactionCount = entry?.compactionCount ?? 0;
	let visibleErrorPayloads = [];
	const parentRunId = params.opts?.runId;
	if (parentRunId) emitAgentRunStatusEvent({
		runId: parentRunId,
		sessionKey: params.sessionKey,
		phase: "memory_flushing"
	});
	const { turnAdoptionLifecycle } = params.followupRun;
	const stopHeartbeat = startFollowupRunPreAdoptionHeartbeat(turnAdoptionLifecycle, abortSignal);
	try {
		if (params.sessionKey) {
			registerAgentRunContext(flushRunId, {
				sessionKey: memorySession.sessionKey,
				sessionId: memorySession.sessionId,
				verboseLevel: params.resolvedVerboseLevel,
				isControlUiVisible: false,
				projectSessionActive: false,
				projectSessionLifecycle: false,
				projectSessionMessages: false
			});
			flushRunRegistered = true;
		}
		memoryFlushLog.debug("memory flush dispatched", {
			event: "memory_flush_dispatched",
			runId: flushRunId,
			sessionKey: memorySession.sessionKey,
			sessionId: memorySession.sessionId,
			sourceSessionKey: params.sessionKey,
			sourceSessionId: entry?.sessionId
		});
		const flushExecution = await runEmbeddedAgentEntry({
			preparedRunAdmission,
			selection: buildRunEntrySelection(selection, params.followupRun.run),
			identity: {
				runId: flushRunId,
				agentId: params.followupRun.run.agentId,
				sessionId: memorySession.sessionId,
				sessionKey: memorySession.sessionKey,
				lane: "main"
			},
			harness: {
				workspaceDir: params.followupRun.run.workspaceDir,
				sessionKey: resolveRuntimePolicySessionKey(),
				preparation: { kind: "direct" },
				resolveRuntimeOverride: (provider) => resolveSessionRuntimeOverrideForProvider({
					provider,
					entry,
					cfg: params.cfg
				})
			},
			behavior: { kind: "maintenance" },
			sessionOverride: { kind: "preserve" },
			abortSignal: deferredLifecycle.signal,
			runCandidate: async (provider, model, runOptions) => {
				const sessionRuntimeOverride = runOptions.agentHarnessRuntimeOverride;
				const candidateThinkLevel = resolveRunThinkingLevelForFallbackCandidate({
					cfg: params.cfg,
					provider,
					modelId: model,
					run: params.followupRun.run,
					catalog: params.followupRun.run.thinkingCatalog,
					agentId: params.followupRun.run.agentId,
					sessionKey: resolveRuntimePolicySessionKey(),
					sessionEntry: entry,
					agentRuntime: sessionRuntimeOverride
				});
				const runBaseParams = await buildEmbeddedRunExecutionParams({
					run: {
						...maintenanceRun,
						thinkLevel: candidateThinkLevel
					},
					sessionCtx: {},
					hasRepliedRef: void 0,
					provider,
					model,
					runId: flushRunId,
					promptCacheKey: params.opts?.promptCacheKey,
					allowTransientCooldownProbe: runOptions.allowTransientCooldownProbe
				});
				const result = await (await embeddedAgentRuntimeLoader.load()).runEmbeddedAgent({
					preparedRunAdmission,
					...runBaseParams,
					...memorySession,
					agentHarnessId: resolveSessionPinnedHarnessId(entry),
					agentHarnessRuntimeOverride: sessionRuntimeOverride,
					sandboxSessionKey: sourcePolicySessionKey,
					memoryAudience: flushMemoryAudience,
					allowGatewaySubagentBinding: true,
					silentExpected: true,
					allowEmptyAssistantReplyAsSilent: true,
					terminalReplyExpectation: "optional",
					trigger: "memory",
					contextTokenBudget: contextWindowTokens,
					memoryFlushWritePath,
					memoryFlushTools,
					initialTurnTainted: !params.followupRun.run.senderIsOwner || sessionLogSnapshot?.turnTainted === true,
					prompt: activeMemoryFlushPlan.prompt,
					transcriptPrompt: "",
					extraSystemPrompt: flushSystemPrompt,
					isFinalFallbackAttempt: runOptions.isFinalFallbackAttempt,
					bootstrapPromptWarningSignaturesSeen,
					bootstrapPromptWarningSignature: bootstrapPromptWarningSignaturesSeen.at(-1),
					abortSignal: deferredLifecycle.signal,
					onDeferredLifecycleOwner: deferredLifecycle.adopt,
					onDeferredLifecycleAbort: deferredLifecycle.abort,
					onRetryWait: deferredLifecycle.beginRetryWait,
					assistantErrorTranscript: runOptions.assistantErrorTranscript,
					authProfileFailurePolicy: runOptions.authProfileFailurePolicy,
					contextEngineLogicalTurnLease: runOptions.contextEngineLogicalTurnLease,
					onContextEngineTurnCandidate: runOptions.onContextEngineTurnCandidate
				});
				visibleErrorPayloads = resolveVisibleMemoryFlushErrorPayloads(result.payloads);
				bootstrapPromptWarningSignaturesSeen = resolveBootstrapWarningSignaturesSeen(result.meta?.systemPromptReport);
				return result;
			}
		});
		deferredLifecycle.signal.throwIfAborted();
		if (visibleErrorPayloads.length > 0) throw buildVisibleMemoryFlushFailure(visibleErrorPayloads);
		if (memoryFlushTools && !persistenceToolCallSucceeded && !memoryFlushResultIsSilent(flushExecution.result)) throw new Error("no persistence tool call succeeded");
		if (params.storePath && params.sessionKey) try {
			const updatedEntry = await updateSessionEntry({
				storePath: params.storePath,
				sessionKey: params.sessionKey
			}, async () => ({ memoryFlush: {
				kind: "succeeded",
				compactionCount: flushedCompactionCount
			} }), {
				skipMaintenance: true,
				takeCacheOwnership: true
			});
			if (updatedEntry) entry = updatedEntry;
		} catch (err) {
			logVerbose(`failed to persist memory flush metadata: ${String(err)}`);
		}
		return {
			sessionEntry: entry,
			outcome: "completed"
		};
	} catch (error) {
		if (error instanceof MemoryFlushToolsUnavailableError) {
			memoryFlushLog.warn(error.message);
			return {
				sessionEntry: entry,
				outcome: "skipped"
			};
		}
		return await recordFailure(error);
	} finally {
		stopHeartbeat?.();
		if (parentRunId && !abortSignal?.aborted) emitAgentRunStatusEvent({
			runId: parentRunId,
			sessionKey: params.sessionKey,
			phase: "preparing_context"
		});
		await deferredLifecycle.complete();
		if (flushRunRegistered) clearAgentRunContext(flushRunId);
		preparedRunAdmission.close();
		preparedAttempt.release();
	}
}
async function recordMemoryFlushFailure(error, run, initialSessionEntry) {
	let sessionEntry = initialSessionEntry;
	let outcome = "failed";
	if ((run.replyOperation?.abortSignal ?? run.abortSignal)?.aborted) {
		logVerbose("memory flush cancelled by its owner");
		return {
			sessionEntry,
			outcome
		};
	}
	const truncatedError = truncateMemoryFlushErrorMessage(error);
	const { sessionKey, storePath } = run;
	if (!isAbortError(error) && storePath && sessionKey) try {
		const adoptEntry = (entry) => {
			if (entry) {
				sessionEntry = entry;
				if (run.sessionStore) run.sessionStore[sessionKey] = entry;
			}
		};
		const updateEntry = (update) => updateSessionEntry({
			storePath,
			sessionKey
		}, update, {
			skipMaintenance: true,
			takeCacheOwnership: true
		});
		const failedEntry = await updateEntry(async (currentEntry) => ({ memoryFlush: {
			kind: "failed",
			...currentEntry.memoryFlush?.compactionCount !== void 0 ? { compactionCount: currentEntry.memoryFlush.compactionCount } : {},
			failureCount: (currentEntry.memoryFlush?.kind === "failed" ? currentEntry.memoryFlush.failureCount : 0) + 1
		} }));
		adoptEntry(failedEntry);
		const failureCount = failedEntry?.memoryFlush?.kind === "failed" ? failedEntry.memoryFlush.failureCount : 0;
		logVerbose(`memory flush failed (attempt ${failureCount}/${MAX_FLUSH_FAILURES}): ${truncatedError}`);
		if (failedEntry && failureCount >= MAX_FLUSH_FAILURES) {
			outcome = "exhausted";
			logVerbose(`memory flush exhausted: skipping flush for this compaction cycle after ${failureCount} consecutive failures`);
			adoptEntry(await updateEntry(async (currentEntry) => ({ memoryFlush: {
				kind: "succeeded",
				compactionCount: currentEntry.compactionCount ?? 0
			} })));
		}
	} catch (persistError) {
		logVerbose(`failed to persist memory flush failure metadata: ${String(persistError)}`);
	}
	else logVerbose(`memory flush run failed: ${String(error)}`);
	return {
		sessionEntry,
		outcome
	};
}
//#endregion
export { runSessionCompactionIfNeeded as n, runMemoryFlushIfNeeded as t };