import { O as getActiveDiagnosticTraceContext } from "./diagnostic-events-BGzDm6gu.js";
import { n as capturePluginLifecycleAuthority } from "./registry-lifecycle-BcLyAL6g.js";
import { d as getActivePluginRegistry } from "./runtime-D0VWfhor.js";
import { i as getPluginRuntimeGatewayRequestScope, r as getGatewayContextResolver, s as withPluginRuntimeGatewayRequestScope } from "./gateway-request-scope-Bj2ffrHm.js";
import { f as loadSessionEntryReadOnly } from "./session-accessor.sqlite-entry-CoLie3L_.js";
import "./session-accessor-Dwfzn6Ej.js";
import { b as runBeforeToolCallHook, l as rewrapToolWithBeforeToolCallHook, m as bindAgentToolSourceExecutionGuard } from "./agent-tools.before-tool-call-DSAdl1_z.js";
import { i as attachInternalToolExecutionPreparer, u as getInternalToolExecutionPreparer } from "./internal-hooks-B-FEfQPl.js";
import { i as getAdmittedRunDelegatedAuthority, l as retainAdmittedRunBeforeToolCallRecovery } from "./admitted-run-context-CFmFMyb8.js";
import { r as copyAgentToolMetadata } from "./agent-tool-metadata-mGvCjYk_.js";
import { n as createCronScheduledToolProjection } from "./exec-tool-target-pinning-Dmc6pGs0.js";
import { a as withGatewayToolCallerIdentity, i as withGatewayToolApprovalOwner, s as wrapToolWithGatewayCallerIdentity, t as createAdmittedGatewayToolCallerIdentity } from "./gateway-caller-context-CWgOcLDg.js";
import { t as callGatewayTool } from "./gateway-vuTMpv-z.js";
import { t as buildAgentHookContextChannelFields } from "./hook-agent-context-C2d6f5XD.js";
import { n as wrapToolWithAbortSignal } from "./agent-tools.abort-BlXys-uw.js";
import { a as getActiveSecretsRuntimeConfigSnapshot } from "./runtime-state-BafpDRCb.js";
import { t as createOpenClawCodingTools } from "./agent-tools-dOQy3UuV.js";
import { o as prepareGitHubToolEnvironment } from "./github-tool-identity-Drvckf8o.js";
import { t as resolveToolLoopDetectionConfig } from "./tool-loop-detection-config-Bmo9y02f.js";
import { s as prepareSystemRunMutableFileApproval } from "./system-run-approval-binding-BTs8abjo.js";
import { t as registerAgentHarnessScheduledToolProjectionCapability } from "./host-private-capabilities-CMFqW9U9.js";
import path from "node:path";
//#region src/agents/harness/node-execution-authority.ts
/** Full is admitted host authority, narrowed to one placement claim, never a request flag. */
function createSessionNodeInvocation(attempt, pluginId, requiredNodeCommands, assertActive, signal) {
	const admittedFull = attempt.permissionMode === "full";
	const resolveContext = getGatewayContextResolver(attempt.admittedRunContext);
	const context = resolveContext?.();
	const target = attempt.sessionTarget;
	const gatewayRegistry = getActivePluginRegistry();
	const pluginOwners = [gatewayRegistry, getPluginRuntimeGatewayRequestScope()?.pluginRegistry ?? gatewayRegistry].map((owner) => {
		const record = owner?.plugins.find((candidate) => candidate.id === pluginId);
		return owner && record ? capturePluginLifecycleAuthority(owner, record, { scopedRuntime: owner !== gatewayRegistry }) : void 0;
	});
	const assertPlacementCurrent = getPluginRuntimeGatewayRequestScope()?.assertNodeExecutionCurrent;
	if (!context || !target?.storePath || !attempt.agentId || !attempt.sessionKey || !attempt.sessionId || !assertPlacementCurrent) return;
	const session = {
		agentId: attempt.agentId,
		sessionKey: attempt.sessionKey,
		storePath: target.storePath
	};
	return async (request, invoke) => {
		if (request.source === "session-full" && (!admittedFull || !requiredNodeCommands.has(request.command))) return;
		const assertCurrent = () => {
			assertActive();
			const entry = loadSessionEntryReadOnly(session);
			if (signal.aborted || getActivePluginRegistry() !== gatewayRegistry || pluginOwners.some((isCurrent) => !isCurrent?.()) || request.source === "session-full" && (attempt.permissionMode !== "full" || !requiredNodeCommands.has(request.command)) || resolveContext && resolveContext() !== context || request.pluginId !== pluginId || !entry || entry.sessionId !== attempt.sessionId || request.source === "session-full" && entry.permissionMode !== "full" || request.workspace.sessionKey !== attempt.sessionKey || request.workspace.sessionId !== attempt.sessionId) throw new Error("admitted node execution authority is no longer current");
			assertPlacementCurrent({
				...request,
				runId: attempt.runId,
				agentId: session.agentId
			});
		};
		assertCurrent();
		const result = await invoke(assertCurrent, signal);
		assertCurrent();
		return result;
	};
}
//#endregion
//#region src/agents/harness/host-capability.ts
const MAX_NATIVE_OPERATION_CWD_BYTES = 4096;
const retainedBeforeToolCallRunners = /* @__PURE__ */ new WeakMap();
/** Internal core-only lease for an already-created host policy callback. */
function retainBeforeToolCallForNativeHookRelay(runBeforeToolCall) {
	return retainedBeforeToolCallRunners.get(runBeforeToolCall)?.();
}
function normalizeNativeOperationCwd(value, attemptCwd) {
	if (typeof value !== "string") throw new Error("native operation cwd must be a string");
	const normalized = value.trim();
	if (!normalized) throw new Error("native operation cwd must not be empty");
	if (Buffer.byteLength(normalized, "utf8") > MAX_NATIVE_OPERATION_CWD_BYTES) throw new Error(`native operation cwd must not exceed ${MAX_NATIVE_OPERATION_CWD_BYTES} bytes`);
	for (let index = 0; index < normalized.length; index += 1) {
		const code = normalized.charCodeAt(index);
		if (code < 32 || code === 127) throw new Error("native operation cwd must not contain control characters");
	}
	return path.resolve(attemptCwd ?? process.cwd(), normalized);
}
function freezeSnapshot(value, seen = /* @__PURE__ */ new WeakSet()) {
	if (!value || typeof value !== "object" || seen.has(value)) return value;
	seen.add(value);
	for (const nested of Object.values(value)) freezeSnapshot(nested, seen);
	return Object.freeze(value);
}
function cloneSnapshot(value) {
	return freezeSnapshot(structuredClone(value));
}
function gateBoundTool(tool, assertActive) {
	const execute = tool.execute;
	const sourcePreparer = getInternalToolExecutionPreparer(tool);
	if (!execute && !sourcePreparer) return tool;
	const gated = {
		...tool,
		...execute ? { execute: async (...args) => {
			assertActive();
			const result = await execute(...args);
			assertActive();
			return result;
		} } : {}
	};
	copyAgentToolMetadata(tool, gated);
	if (sourcePreparer) attachInternalToolExecutionPreparer(gated, async (preparationParams) => {
		assertActive();
		const prepared = await sourcePreparer(preparationParams);
		try {
			assertActive();
		} catch (error) {
			prepared.dispose();
			throw error;
		}
		if (prepared.kind === "immediate") return prepared;
		return {
			...prepared,
			execute: async (onImplementationStart) => {
				assertActive();
				const result = await prepared.execute(onImplementationStart);
				assertActive();
				return result;
			}
		};
	});
	return gated;
}
function createBoundCallerIdentity(params, receiptAuthority) {
	return createAdmittedGatewayToolCallerIdentity({
		admittedRunContext: params.admittedRunContext,
		receiptAuthority,
		agentId: params.agentId,
		sessionKey: params.sessionKey,
		turnSourceChannel: params.messageChannel ?? params.messageProvider,
		turnSourceTo: params.currentMessagingTarget ?? params.currentChannelId,
		turnSourceAccountId: params.agentAccountId,
		turnSourceThreadId: params.currentThreadTs
	});
}
/** Creates a closure-bound capability before plugin invocation. */
function createAgentHarnessHostCapabilities(params) {
	const attempt = params.attempt;
	const requiredNodeCommands = new Set(params.requiredNodeCommands);
	const operationalRunInstance = attempt.admittedRunContext.operationalRunInstance;
	const delegatedAuthority = getAdmittedRunDelegatedAuthority(attempt.admittedRunContext);
	if (!delegatedAuthority) throw new Error("agent harness host capability requires active admitted run authority");
	let active = true;
	const capabilityAbortController = new AbortController();
	const callerIdentity = createBoundCallerIdentity(attempt, assertActive);
	function assertActive() {
		if (!active || attempt.admittedRunContext.operationalRunInstance !== operationalRunInstance || getAdmittedRunDelegatedAuthority(attempt.admittedRunContext) !== delegatedAuthority || callerIdentity?.gatewayContextResolver !== void 0 && callerIdentity.gatewayContextResolver() === void 0) throw new Error("agent harness host capability is no longer active");
	}
	const requester = {
		...attempt.messageChannel ?? attempt.messageProvider ? { channel: attempt.messageChannel ?? attempt.messageProvider ?? void 0 } : {},
		...attempt.agentAccountId ? { accountId: attempt.agentAccountId } : {},
		...attempt.senderId ? { senderId: attempt.senderId } : {},
		...attempt.senderIsOwner !== void 0 ? { senderIsOwner: attempt.senderIsOwner } : {},
		...attempt.memberRoleIds?.length ? { roleIds: Object.freeze([...attempt.memberRoleIds]) } : {}
	};
	const config = attempt.config ? cloneSnapshot(attempt.config) : void 0;
	const skillsSnapshot = attempt.skillsSnapshot ? cloneSnapshot(attempt.skillsSnapshot) : void 0;
	const preparedRunEnvironment = prepareGitHubToolEnvironment({
		config: config ?? {},
		sourceConfig: getActiveSecretsRuntimeConfigSnapshot()?.sourceConfig,
		agentId: attempt.agentId ?? "main"
	});
	const skillUsagePaths = attempt.sandbox?.skillUsagePaths ? cloneSnapshot(attempt.sandbox.skillUsagePaths) : void 0;
	const hookContext = Object.freeze({
		...attempt.agentId ? { agentId: attempt.agentId } : {},
		...config ? { config } : {},
		...attempt.cwd ? { cwd: attempt.cwd } : {},
		...attempt.workspaceDir ? { workspaceDir: attempt.workspaceDir } : {},
		...attempt.sessionKey ? { sessionKey: attempt.sessionKey } : {},
		...attempt.sessionId ? { sessionId: attempt.sessionId } : {},
		runId: attempt.runId,
		...buildAgentHookContextChannelFields(attempt),
		...Object.keys(requester).length > 0 ? { requester: Object.freeze(requester) } : {},
		...getActiveDiagnosticTraceContext() ? { trace: getActiveDiagnosticTraceContext() } : {},
		...skillsSnapshot ? { skillsSnapshot } : {},
		...skillUsagePaths ? { skillUsagePaths } : {},
		...attempt.onToolOutcome ? { onToolOutcome: attempt.onToolOutcome } : {},
		...attempt.allocateToolOutcomeOrdinal ? { allocateToolOutcomeOrdinal: attempt.allocateToolOutcomeOrdinal } : {},
		...attempt.sandbox?.enabled && attempt.sandbox.workspaceAccess === "rw" && attempt.sandbox.fsBridge ? { sandbox: Object.freeze({
			root: attempt.sandbox.workspaceDir,
			bridge: attempt.sandbox.fsBridge
		}) } : {},
		loopDetection: cloneSnapshot(resolveToolLoopDetectionConfig({
			cfg: config,
			agentId: attempt.agentId
		})),
		trigger: attempt.trigger,
		approvalReviewerDeviceId: attempt.approvalReviewerDeviceId,
		turnSourceChannel: attempt.messageChannel ?? attempt.messageProvider,
		turnSourceTo: attempt.currentMessagingTarget ?? attempt.currentChannelId,
		turnSourceAccountId: attempt.agentAccountId,
		turnSourceThreadId: attempt.currentThreadTs
	});
	const withCaller = async (run) => await withGatewayToolCallerIdentity(callerIdentity, run);
	const runBeforeToolCallWithAssertion = async (assertCurrent, { nativeOperation, approvalMode, ...request }) => {
		assertCurrent();
		const hostApprovalMode = approvalMode === "defer" ? "defer" : "request";
		const actionCwd = nativeOperation?.cwd !== void 0 ? normalizeNativeOperationCwd(nativeOperation.cwd, hookContext.cwd) : void 0;
		const actionHookContext = actionCwd ? Object.freeze({
			...hookContext,
			cwd: actionCwd
		}) : hookContext;
		const result = await runBeforeToolCallHook({
			...request,
			approvalMode: hostApprovalMode,
			ctx: actionHookContext
		});
		assertCurrent();
		return result;
	};
	const runBeforeToolCall = async (request) => await withCaller(async () => await runBeforeToolCallWithAssertion(assertActive, request));
	retainedBeforeToolCallRunners.set(runBeforeToolCall, () => {
		const recovery = retainAdmittedRunBeforeToolCallRecovery(attempt.admittedRunContext);
		if (!recovery) return;
		const assertRecoveryActive = () => {
			if (attempt.abortSignal?.aborted || attempt.admittedRunContext.operationalRunInstance !== operationalRunInstance || callerIdentity?.gatewayContextResolver !== void 0 && callerIdentity.gatewayContextResolver() === void 0) throw new Error("agent harness retained host policy is no longer active");
			recovery.assertActive();
		};
		return Object.freeze({
			assertActive: assertRecoveryActive,
			release: recovery.release,
			runBeforeToolCall: async (request) => await runBeforeToolCallWithAssertion(assertRecoveryActive, request)
		});
	});
	const trajectoryRecorder = attempt.trajectoryRecorder;
	const scheduledToolSources = /* @__PURE__ */ new WeakMap();
	const bindToolSurface = (tools, options) => {
		assertActive();
		const boundAbortSignal = attempt.abortSignal ? AbortSignal.any([attempt.abortSignal, capabilityAbortController.signal]) : capabilityAbortController.signal;
		const bindingCwd = options?.cwd !== void 0 ? normalizeNativeOperationCwd(options.cwd, hookContext.cwd) : void 0;
		const bindingHookContext = bindingCwd ? Object.freeze({
			...hookContext,
			cwd: bindingCwd
		}) : hookContext;
		return tools.map((tool) => bindAgentToolSourceExecutionGuard(tool, assertActive)).map((tool) => rewrapToolWithBeforeToolCallHook(tool, bindingHookContext)).map((tool) => callerIdentity ? wrapToolWithGatewayCallerIdentity(tool, callerIdentity) : tool).map((tool) => wrapToolWithAbortSignal(tool, boundAbortSignal)).map((tool) => gateBoundTool(tool, assertActive));
	};
	const capabilities = Object.freeze({
		kind: "agent-harness-host-capability",
		version: 1,
		assertActive,
		...trajectoryRecorder ? { trajectory: Object.freeze({
			recordEvent: (type, data) => {
				assertActive();
				trajectoryRecorder.recordEvent(type, data);
			},
			flush: async () => {
				assertActive();
				await trajectoryRecorder.flush();
				assertActive();
			}
		}) } : {},
		preparedEnvironment: () => {
			assertActive();
			return Object.freeze({
				credentialScrubEnv: Object.freeze({ ...preparedRunEnvironment.credentialScrubEnv }),
				localIdentityEnv: Object.freeze({ ...preparedRunEnvironment.localIdentityEnv }),
				managedLocalIdentity: preparedRunEnvironment.managedLocalIdentity
			});
		},
		bindToolSurface,
		createToolSurface: (options, bindingOptions) => {
			assertActive();
			const tools = bindToolSurface(createOpenClawCodingTools({
				...options,
				operationalRunInstance
			}), bindingOptions);
			for (const tool of tools) if (tool.name === "exec" || tool.name === "process") scheduledToolSources.set(tool, Object.freeze({
				targetTool: tool.name,
				execute: tool.execute
			}));
			return tools;
		},
		prepareMutableFileApproval: async (request) => {
			assertActive();
			const prepared = await prepareSystemRunMutableFileApproval(request);
			assertActive();
			if (!prepared.ok) return prepared;
			return Object.freeze({
				ok: true,
				requiresOneShot: prepared.requiresOneShot,
				revalidate: async () => {
					assertActive();
					const current = await prepared.revalidate();
					assertActive();
					return current;
				}
			});
		},
		runBeforeToolCall,
		requestApproval: async (request) => {
			assertActive();
			const result = await withCaller(async () => await withGatewayToolApprovalOwner(params.pluginId, async () => await callGatewayTool("plugin.approval.request", { timeoutMs: request.transportTimeoutMs ?? request.timeoutMs }, {
				title: request.title,
				description: request.description,
				severity: request.severity,
				toolName: request.toolName,
				toolCallId: request.toolCallId,
				timeoutMs: request.timeoutMs,
				twoPhase: true,
				...request.allowedDecisions ? { allowedDecisions: request.allowedDecisions } : {}
			}, {
				expectFinal: false,
				requireAgentRuntimeIdentity: true
			})));
			assertActive();
			return result;
		},
		waitForApproval: async (request) => {
			assertActive();
			const result = await withCaller(async () => await callGatewayTool("plugin.approval.waitDecision", { timeoutMs: request.transportTimeoutMs ?? request.timeoutMs }, { id: request.approvalId }, { signal: request.signal }));
			assertActive();
			if (result?.id !== request.approvalId) return;
			return {
				decision: result.decision,
				terminalReason: result.terminalReason
			};
		}
	});
	registerAgentHarnessScheduledToolProjectionCapability({
		hostCapabilities: capabilities,
		ownerPluginId: params.pluginId,
		create: (sourceTool, projection) => {
			assertActive();
			const source = scheduledToolSources.get(sourceTool);
			if (!source || sourceTool.name !== source.targetTool || sourceTool.execute !== source.execute) throw new Error("scheduled tool projection source was not created by this host capability");
			return createCronScheduledToolProjection(sourceTool, assertActive, source.targetTool, projection);
		}
	});
	return {
		capabilities,
		runWithScope: (run) => withPluginRuntimeGatewayRequestScope({
			isWebchatConnect: () => false,
			...getPluginRuntimeGatewayRequestScope(),
			invokeWithSessionNodeAuthority: createSessionNodeInvocation(attempt, params.pluginId, requiredNodeCommands, assertActive, attempt.abortSignal ? AbortSignal.any([attempt.abortSignal, capabilityAbortController.signal]) : capabilityAbortController.signal)
		}, run),
		close: () => {
			if (!active) return;
			active = false;
			capabilityAbortController.abort();
		}
	};
}
//#endregion
export { retainBeforeToolCallForNativeHookRelay as n, createAgentHarnessHostCapabilities as t };
