openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
1,128 lines • 54.5 kB
JavaScript
import { a as resolveGlobalSingleton } from "./global-singleton-0m-JziJW.mjs";
import { r as getAsyncWorkSignal } from "./async-work-scope-DDiH0P7W.mjs";
import { t as containsAsciiControlCharacter } from "./string-normalization-D6DKCpwE.mjs";
import { c as isPathInside$1, m as readLocalFileFromRoots, x as resolveLocalPathFromRootsSync } from "./fs-safe-BBzelG8F.mjs";
import { n as assertDatabasePathIdentity } from "./sqlite-worker-identity-BRNRpRyc.mjs";
import { k as getActiveDiagnosticTraceContext } from "./diagnostic-events-DT4ejwoa.mjs";
import { r as sha256HexPrefixCore } from "./node-crypto-BG4u3UnX.mjs";
import "./crypto-digest-y6oZN-_F.mjs";
import { o as isSameOpenClawAgentDatabasePath } from "./openclaw-agent-db.paths-BbmZlEP5.mjs";
import { n as captureOpenClawStateReadWorkerContext } from "./openclaw-state-worker-context-BvvgY6-t.mjs";
import { o as openOpenClawAgentDatabase } from "./openclaw-agent-db-DWI9Bgur.mjs";
import { i as normalizePathPrepend, n as findPathKey, t as applyPathPrepend } from "./path-prepend-D21kYd3c.mjs";
import { g as resolveSessionAgentIdStrict } from "./agent-scope-bJOokm5r.mjs";
import { g as getGatewayContextResolver, l as withPluginRuntimeGatewayRequestScope, o as getPluginRuntimeGatewayRequestScope } from "./gateway-request-scope-DV3FHtde.mjs";
import { o as isToolExecutionAllowed } from "./tool-policy-shared-CNWjndK7.mjs";
import { f as getAgentRunLifecycleGeneration } from "./agent-run-registry-Cm8FlLIi.mjs";
import { u as emitAgentRunOutputTokens, v as registerAgentEventLifecycleRotationHandler } from "./agent-events-jWdQ_ESE.mjs";
import { a as composeSessionSourceAssertion, i as captureExternalSessionCommitGuard } from "./session-source-authority-h1UO3u0I.mjs";
import { a as capturePluginLifecycleAuthority } from "./registry-lifecycle-PK-HWmev.mjs";
import { l as getActivePluginRegistry } from "./runtime-U4i1bMh7.mjs";
import { a as withInstallationTarget, n as getInstallationTarget, r as installationTargetEnv } from "./installation-target-context-BIGIART1.mjs";
import { c as getOwnedSessionTranscriptWriterFence } from "./transcript-write-context-DwwjCPCE.mjs";
import { g as throwAgentRunRestartAbortReason } from "./run-termination-5c-0T0hN.mjs";
import { c as rewrapToolWithBeforeToolCallHook, v as runBeforeToolCallHook } from "./agent-tools.before-tool-call-CQkX3nOj.mjs";
import { o as getActiveSecretsRuntimeConfigSnapshot } from "./runtime-state-B9uZIjU9.mjs";
import { i as captureAdmittedRunActiveAssertion, m as readAdmittedRunOperatorAuthority, r as bindOperatorModelExecution, t as assertAdmittedRunOperatorAuthority, u as getAdmittedRunDelegatedAuthority, y as retainAdmittedRunBeforeToolCallRecovery } from "./admitted-run-context-D0yzk2io.mjs";
import { f as readPersistedMediaFacts } from "./media-facts-BIPREXi-.mjs";
import { c as waitForSessionTranscriptProjection } from "./session-transcript-reconcile-BwrFIOby.mjs";
import { d as sessionTranscriptIndexNeedsReconcile } from "./session-transcript-index-D-T7svZQ.mjs";
import { s as getUserTurnTranscriptAdmissionOwner } from "./session-transcript-read-fence-DqVaDIch.mjs";
import { r as readActiveTranscriptEntryAnchor } from "./session-accessor.sqlite-transcript-anchor-VJSh_9H1.mjs";
import { h as redactTranscriptMessage } from "./session-accessor.sqlite-transcript-store-D63Niwm2.mjs";
import { r as sessionMatchesExpectedTranscriptTurn } from "./session-transcript-turn-state-Bqkxfhzx.mjs";
import { n as publishTranscriptUpdate } from "./session-accessor.sqlite-events-x56_8OQX.mjs";
import { o as loadSessionEntry, s as loadSessionEntryReadOnly } from "./session-accessor.sqlite-entry-DLa7_9ui.mjs";
import "./session-accessor-C3ljJ974.mjs";
import { i as resolveSessionTranscriptDatabasePath } from "./session-accessor.transcript-target-DdAdqCJ1.mjs";
import { d as withGatewayToolApprovalOwner, f as withGatewayToolCallerIdentity, g as wrapToolWithGatewayCallerIdentity, n as captureGatewayToolReceiptAssertion, o as getGatewayToolCallerIdentity, r as createAdmittedGatewayToolCallerIdentity } from "./gateway-caller-context-CU8n6n_e.mjs";
import { i as copyAgentToolMetadata, u as createCronScheduledToolProjection } from "./agent-tool-metadata-DU21au_v.mjs";
import { a as attachInternalToolExecutionPreparer, m as getInternalToolExecutionPreparer } from "./internal-hooks-CSjTREUl.mjs";
import { r as markToolExecutionNotStarted } from "./tool-effect-receipt-BHVAm8DM.mjs";
import { S as withAgentQuestionAnswerAuthority, _ as registerAgentHarnessTtsProvenanceTransferCapability, b as resolveAgentQuestionAnswerAuthority, g as registerAgentHarnessScheduledToolProjectionCapability, m as registerAgentHarnessBeforeToolCallRetention } from "./host-private-capabilities-BL8gRbZP.mjs";
import { n as resolveEffectiveToolFsWorkspaceOnly } from "./tool-fs-policy-D543Bcua.mjs";
import "./tool-result-error-CN2enaAJ.mjs";
import { t as callGatewayTool } from "./gateway-1wftaKTM.mjs";
import { t as bindAgentToolSourceExecutionGuard } from "./agent-tool-source-execution-guard-DVdlO49-.mjs";
import { n as rewritePreparedTranscriptMessageAtAnchor } from "./session-message-rewrite-BcYdAXSy.mjs";
import { t as buildActiveNodeContextText } from "./active-node-context-DpQMef3G.mjs";
import { t as registerMcpToolApprovalBinding } from "./mcp-tool-approval-binding-DPk7uogO.mjs";
import { s as prepareSystemRunMutableFileApproval } from "./system-run-approval-binding-Cl9jeqJB.mjs";
import { t as buildAgentHookContextChannelFields } from "./hook-agent-context-vC-cM68i.mjs";
import { a as prepareSkillLibrarySelection } from "./selection-CLpBV2Ib.mjs";
import { t as resolveSkillResourceCandidates } from "./resource-candidates-DNAiWHXM.mjs";
import { m as wrapToolWithAbortSignal } from "./tool-contract-error-CznWpQuP.mjs";
import { i as createOpenClawCodingToolsInternalAsync, r as createOpenClawCodingToolsInternal } from "./agent-tools-Bpi7xWYy.mjs";
import { n as resolveExecToolConfig } from "./lazy-exec-tool-CzsaJ12F.mjs";
import { l as prepareGitHubToolEnvironment } from "./github-tool-identity-DbK12gfx.mjs";
import { c as MAX_SKILL_INSTRUCTION_BYTES } from "./openclaw-tools-CSSYZDKR.mjs";
import { t as resolveToolLoopDetectionConfig } from "./tool-loop-detection-config-TObMWR7t.mjs";
import { o as transferCoreTtsToolResultProvenance, r as getCoreTtsToolResultMediaUrls } from "./tts-tool-result-provenance-BbSbWcUn.mjs";
import { t as log } from "./logger-Wi08e7sJ.mjs";
import { t as runBestEffortCallback } from "./embedded-agent-subscribe.callback-BBye3ou6.mjs";
import { t as bindHarnessReplyMedia } from "./reply-media-Bb5hFDcH.mjs";
import { i as resolveSandboxSkillRuntimeInputs } from "./sandbox-skills-Dcyg2gP3.mjs";
import { t as prepareInstalledSkillCatalog } from "./installed-skill-runtime-DbhuKfkX.mjs";
import { t as formatHarnessApprovalPresentation } from "./native-hook-relay-approval-presentation-DqaPxQB-.mjs";
import path from "node:path";
import { isDeepStrictEqual } from "node:util";
import { isPathInsideWithRealpath } from "@openclaw/fs-safe/path";
//#region src/sessions/user-turn-transcript-annotation.ts
/** Core-only binding performed by the harness host before invoking plugin code. */
function bindUserTurnTranscriptAnnotation(params) {
const owner = getUserTurnTranscriptAdmissionOwner(params.recorder);
const receipt = owner?.receipt();
const message = owner?.message();
if (!owner || !receipt || !message || owner.blocked() || message.excludeFromContext === true) return;
let admission = structuredClone(receipt);
let admittedMessage = structuredClone(message);
const target = { ...params.target };
const selected = loadSessionEntry({
...target,
readConsistency: "latest"
});
const fence = getOwnedSessionTranscriptWriterFence({ sessionTarget: target });
if (target.sessionId !== admission.sessionId || target.sessionKey !== admission.sessionKey || target.agentId !== admission.agentId || !isSameOpenClawAgentDatabasePath(resolveSessionTranscriptDatabasePath(target), admission.storePath) || !selected || selected.sessionId !== admission.sessionId || selected.activeWriterRunId !== void 0 && selected.activeWriterRunId !== params.runId) return;
const expectedLifecycleRevision = target.expectedLifecycleRevision ?? fence?.expectedLifecycleRevision ?? selected.lifecycleRevision ?? null;
const expectedWriterRunId = target.expectedWriterRunId ?? fence?.expectedWriterRunId;
const assertLive = () => {
params.assertCurrent();
if (params.abortSignal?.aborted || owner.blocked() || !isDeepStrictEqual(owner.receipt(), admission) || !isDeepStrictEqual(owner.message(), admittedMessage) || admittedMessage["__openclaw"]?.steerTargetRunId !== void 0) throw new Error("current user admission is no longer available for native annotation");
};
const assertCurrent = () => {
assertLive();
const current = loadSessionEntry({
...target,
readConsistency: "latest"
});
const { logicalTurnId: _logicalTurnId, role: _role, ...anchor } = admission;
if (!sessionMatchesExpectedTranscriptTurn(current ? { entry: current } : void 0, {
expectedSessionId: admission.sessionId,
expectedLifecycleRevision,
expectedWriterRunId
}) || fence?.expectedWriterRunId !== void 0 && current?.activeWriterRunId !== fence.expectedWriterRunId || fence?.expectedLifecycleRevision !== void 0 && current?.lifecycleRevision !== fence.expectedLifecycleRevision || current?.activeWriterRunId !== selected.activeWriterRunId || sessionTranscriptIndexNeedsReconcile(openOpenClawAgentDatabase({
agentId: admission.agentId,
path: admission.storePath
}).db, admission.sessionId) || !isDeepStrictEqual(readActiveTranscriptEntryAnchor(admission), anchor)) throw new Error("current user admission is no longer available for native annotation");
};
return async (annotation) => {
const fields = {
mirrorIdentity: annotation.mirrorIdentity,
upstreamUserText: annotation.upstreamUserText,
mirrorOrigin: annotation.mirrorOrigin,
mirrorSourceFingerprint: annotation.mirrorSourceFingerprint,
runId: params.runId
};
if (Object.values(fields).some((value) => typeof value !== "string") || !fields.mirrorIdentity || !fields.mirrorOrigin || !fields.mirrorSourceFingerprint) throw new Error("native prompt annotation requires complete provenance");
assertCurrent();
if (sha256HexPrefixCore(JSON.stringify({
role: "user",
content: admittedMessage.content,
upstreamUserText: fields.upstreamUserText || void 0
}), 32) !== fields.mirrorSourceFingerprint) throw new Error("native prompt annotation does not match admitted content");
let verified = false;
const { logicalTurnId: _logicalTurnId, role: _role, ...anchor } = admission;
const rewritten = await rewritePreparedTranscriptMessageAtAnchor(anchor, (current) => {
assertLive();
if (!isDeepStrictEqual(current, admittedMessage)) throw new Error("native prompt annotation cannot replace an edited admission");
const metadata = admittedMessage["__openclaw"] ?? {};
if (metadata.runTerminal !== void 0 || Object.entries(fields).some(([key, value]) => metadata[key] !== void 0 && metadata[key] !== value)) throw new Error("native prompt annotation conflicts with recorded provenance");
const next = {
...admittedMessage,
__openclaw: {
...metadata,
...fields
}
};
if (!isDeepStrictEqual(redactTranscriptMessage(next, params.config), next)) throw new Error("native prompt annotation would restore redacted evidence");
verified = true;
return isDeepStrictEqual(next, admittedMessage) ? void 0 : next;
}, {
active: "exact",
expectedEntry: {
lifecycleRevision: expectedLifecycleRevision,
activeWriterRunId: selected.activeWriterRunId ?? null
},
assertCurrent: assertLive,
assertNativeCurrent: assertCurrent
});
if (!verified) throw new Error("native prompt admission disappeared before annotation");
if (rewritten) {
admission = {
...admission,
generation: rewritten.generation
};
admittedMessage = structuredClone(rewritten.message);
owner.refresh({ ...admission }, rewritten.message);
await waitForSessionTranscriptProjection(admission, params.abortSignal);
}
assertCurrent();
if (rewritten) {
await publishTranscriptUpdate(admission, {
message: rewritten.message,
messageId: admission.entryId,
messageSeq: admission.activeMessagePosition + 1
});
assertCurrent();
}
};
}
//#endregion
//#region src/agents/harness/host-bound-tool.ts
function gateBoundTool(tool, assertActive, observeResult) {
const execute = tool.execute;
const sourcePreparer = getInternalToolExecutionPreparer(tool);
if (!execute && !sourcePreparer) return tool;
const acceptResult = (result) => {
assertActive();
observeResult(result);
return result;
};
const gated = {
...tool,
...execute ? { execute: async (...args) => {
try {
assertActive();
} catch (error) {
throw markToolExecutionNotStarted(error);
}
return acceptResult(await execute(...args));
} } : {}
};
copyAgentToolMetadata(tool, gated, (source) => gateBoundTool(source, assertActive, observeResult));
if (sourcePreparer) attachInternalToolExecutionPreparer(gated, async (preparationParams) => {
assertActive();
const prepared = await sourcePreparer(preparationParams);
try {
assertActive();
} catch (error) {
prepared.dispose();
throw error;
}
if (prepared.kind === "immediate") {
if (prepared.outcome.kind === "result") observeResult(prepared.outcome.result);
return prepared;
}
return {
...prepared,
execute: async (onImplementationStart) => {
assertActive();
return acceptResult(await prepared.execute(onImplementationStart));
}
};
});
return gated;
}
//#endregion
//#region src/agents/harness/host-snapshot.ts
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);
}
/** Host capabilities retain immutable input facts independently of caller mutation. */
function cloneHostSnapshot(value) {
return freezeSnapshot(structuredClone(value));
}
//#endregion
//#region src/agents/harness/host-capability-workspace.ts
function captureRequiredWorkspaceToolFloor(attempt, pluginId, config) {
if (attempt.requireWorkspaceOnly !== true) return;
const requiredWorkspace = {
workspaceDir: attempt.workspaceDir,
cwd: attempt.cwd ?? attempt.workspaceDir,
root: attempt.sandbox?.enabled ? attempt.sandbox.workspaceDir : attempt.sessionRoot ?? attempt.workspaceDir,
sandbox: attempt.sandbox ? Object.freeze({
...attempt.sandbox,
tools: cloneHostSnapshot(attempt.sandbox.tools)
}) : void 0,
permissionMode: attempt.permissionMode
};
if (!requiredWorkspace.workspaceDir || !requiredWorkspace.root) throw new Error("required workspace tool surface has no captured root");
const root = requiredWorkspace.root;
const apply = (options) => {
const requestedPermissionRoot = options?.sessionPermissionPolicy?.root;
if (requestedPermissionRoot && requestedPermissionRoot !== root && !isPathInsideWithRealpath(root, requestedPermissionRoot)) throw new Error("tool permission root escapes the captured required workspace");
return {
config,
workspaceDir: requiredWorkspace.workspaceDir,
cwd: requiredWorkspace.cwd,
sandbox: requiredWorkspace.sandbox,
requireWorkspaceOnly: true,
sessionPermissionPolicy: requiredWorkspace.permissionMode || options?.sessionPermissionPolicy ? {
root: requestedPermissionRoot ?? root,
mode: requiredWorkspace.permissionMode === "read-only" || options?.sessionPermissionPolicy?.mode === "read-only" ? "read-only" : requiredWorkspace.permissionMode ?? options.sessionPermissionPolicy.mode
} : void 0,
...pluginId === "codex" ? {
exec: {
...options?.exec,
mode: "deny"
},
toolConstructionPlan: {
...options?.toolConstructionPlan ?? {
includeBaseCodingTools: options?.includeCoreTools !== false,
includeChannelTools: options?.includeCoreTools !== false,
includeOpenClawTools: options?.includeCoreTools !== false,
includePluginTools: true
},
includeShellTools: false
}
} : {}
};
};
return {
root,
apply
};
}
//#endregion
//#region src/agents/harness/host-environment.ts
const MAX_NATIVE_OPERATION_CWD_BYTES = 4096;
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`);
if (containsAsciiControlCharacter(normalized)) throw new Error("native operation cwd must not contain control characters");
return path.resolve(attemptCwd ?? process.cwd(), normalized);
}
/** Capture non-secret environment facts once; the harness owns their placement. */
function prepareAgentHarnessEnvironment(params) {
const execConfig = resolveExecToolConfig({
cfg: params.config,
agentId: params.sandboxAgentId ?? resolveSessionAgentIdStrict(params)
});
const hasConfiguredPrefix = normalizePathPrepend(execConfig.configuredPathPrepend).length > 0;
const pathKey = findPathKey(process.env);
const localToolEnv = hasConfiguredPrefix ? { [pathKey]: process.env[pathKey] ?? "" } : void 0;
const localToolPathPrepend = hasConfiguredPrefix ? Object.freeze(normalizePathPrepend(execConfig.pathPrepend)) : void 0;
if (localToolEnv && localToolPathPrepend) {
applyPathPrepend(localToolEnv, [...localToolPathPrepend]);
Object.freeze(localToolEnv);
}
const identity = prepareGitHubToolEnvironment({
config: params.config ?? {},
sourceConfig: getActiveSecretsRuntimeConfigSnapshot()?.sourceConfig,
agentId: params.agentId ?? "main"
});
const localProcessEnv = installationTargetEnv(params.installationTarget);
return Object.freeze({
credentialScrubEnv: Object.freeze({ ...identity.credentialScrubEnv }),
localIdentityEnv: Object.freeze({ ...identity.localIdentityEnv }),
managedLocalIdentity: identity.managedLocalIdentity,
...localProcessEnv ? { localProcessEnv } : {},
...localToolEnv ? {
localToolEnv,
localToolPathPrepend
} : {}
});
}
//#endregion
//#region src/agents/harness/context-media.ts
/** Captures media policy before plugin invocation while keeping extraction dependencies lazy. */
function bindHarnessContextMedia(params) {
const { attempt, config, assertActive } = params;
if (!attempt.workspaceDir || !attempt.model) return;
const modelInput = structuredClone(attempt.model.input);
Object.freeze(modelInput);
const contextMedia = Object.freeze({
config,
workspaceDir: attempt.sandbox?.enabled ? attempt.sandbox.workspaceDir : attempt.workspaceDir,
agentWorkspaceDir: attempt.workspaceDir,
modelInput,
agentId: attempt.agentId,
channelId: attempt.messageChannel ?? attempt.messageProvider,
accountId: attempt.agentAccountId,
...attempt.sandbox?.enabled && attempt.sandbox.fsBridge ? { sandbox: Object.freeze({
root: attempt.sandbox.workspaceDir,
bridge: attempt.sandbox.fsBridge
}) } : {}
});
const assertCurrent = () => {
assertActive();
attempt.abortSignal?.throwIfAborted();
};
return async (request) => {
assertCurrent();
const { prepareHarnessContextMedia } = await import("./context-media-runtime-AbfaH1Io.mjs");
assertCurrent();
const result = await prepareHarnessContextMedia({
...request,
...contextMedia,
assertCurrent
});
assertCurrent();
return result;
};
}
//#endregion
//#region src/agents/harness/input-attachments.ts
/** Capture original input and policy before the plugin confirms actual execution placement. */
function bindHarnessInputAttachments(params) {
const { attempt, config, assertActive } = params;
const attemptSignal = attempt.abortSignal;
const inputWorkspaceDir = attempt.workspaceDir;
const inputTimeoutMs = attempt.timeoutMs;
const initialInput = {
media: structuredClone(attempt.inputAttachmentMedia ?? attempt.media),
userTurnTranscriptRecorder: attempt.userTurnTranscriptRecorder
};
const resolveInputAttachmentMedia = async () => {
assertActive();
attemptSignal?.throwIfAborted();
const recorder = initialInput.userTurnTranscriptRecorder;
const message = await recorder?.resolveMessage() ?? recorder?.message;
assertActive();
attemptSignal?.throwIfAborted();
const media = structuredClone((message ? readPersistedMediaFacts(message) : void 0) ?? initialInput.media ?? []);
return Object.freeze(media.map((fact) => Object.freeze(fact)));
};
const inputPolicyEligible = !attempt.sandbox?.enabled && !attempt.requireWorkspaceOnly && !attempt.modelRun && attempt.promptMode !== "none" && (!attempt.permissionMode || attempt.permissionMode === "full") && !resolveEffectiveToolFsWorkspaceOnly({
cfg: config,
agentId: attempt.agentId
});
let inputReadAllowed = false;
return {
resolveInputAttachmentMedia,
prepareInputAttachments: inputWorkspaceDir && inputTimeoutMs !== void 0 ? async (request) => {
const assertCurrent = () => {
assertActive();
attemptSignal?.throwIfAborted();
request.signal?.throwIfAborted();
request.assertCurrent();
};
assertCurrent();
if (!inputReadAllowed || !inputPolicyEligible) return;
const { prepareAgentWorkspaceAttachments } = await import("./workspace-access-BCJc9MfQ.mjs");
assertCurrent();
const result = await prepareAgentWorkspaceAttachments({
workspaceDir: inputWorkspaceDir,
localExecution: {
config,
readAllowed: inputReadAllowed,
maxChars: request.maxChars
},
turn: {
...request.turn ?? initialInput,
config,
timeoutMs: inputTimeoutMs,
abortSignal: request.signal ?? attemptSignal
},
assertCurrent
});
assertCurrent();
return result;
} : void 0,
setInputAttachmentReadAllowed: (allowed) => {
assertActive();
inputReadAllowed = allowed;
}
};
}
//#endregion
//#region src/agents/harness/host-media.ts
/** Bind media capabilities to the same captured attempt policy and host lifetime. */
function bindHarnessMedia(params) {
const { resolveInputAttachmentMedia, prepareInputAttachments, setInputAttachmentReadAllowed } = bindHarnessInputAttachments(params);
const prepareContextMedia = bindHarnessContextMedia(params);
const prepareReplyMedia = bindHarnessReplyMedia(params);
return {
capabilities: {
resolveInputAttachmentMedia,
...prepareContextMedia ? { prepareContextMedia } : {},
...prepareInputAttachments ? { prepareInputAttachments } : {},
...prepareReplyMedia ? { prepareReplyMedia } : {}
},
setInputAttachmentReadAllowed
};
}
//#endregion
//#region src/agents/harness/host-skills.ts
/** Keep pinned resources and their physical source through awaited tool construction. */
async function prepareHostSkillLibraryResources(selections, assertActive) {
const context = captureOpenClawStateReadWorkerContext();
const identity = context.admission.identity;
const assertSourceCurrent = () => {
context.maintenanceScope?.assertAdmission();
context.admission.assertCurrent();
};
const assertCurrent = () => {
assertActive();
assertSourceCurrent();
};
return {
entries: cloneHostSnapshot(await prepareSkillLibrarySelection(selections, { env: context.environment }, assertCurrent)),
assertCurrent,
assertPublicationCurrent: () => {
assertSourceCurrent();
assertDatabasePathIdentity(context.admission.databasePath, identity);
}
};
}
/** Catalog identity is host-owned; readable paths follow the effective tool placement. */
function bindHostSkillCatalog(params) {
return (placement, permissionRoot) => {
params.assertCurrent();
if (!params.readable) return [];
const sandbox = params.sandbox?.enabled ? params.sandbox : placement ?? params.sandbox;
const inputs = resolveSandboxSkillRuntimeInputs({
sandbox,
skillsAnchorWorkspace: params.workspaceDir,
skillsSnapshot: params.snapshot
});
const catalog = prepareInstalledSkillCatalog({
snapshot: inputs.skillsSnapshot,
workspaceDir: inputs.skillsWorkspaceDir,
sandbox,
assertCurrent: params.assertCurrent
});
if (!params.requiredRoot) return catalog;
const requiredRoot = permissionRoot ?? params.requiredRoot;
if (!isPathInside$1(params.requiredRoot, requiredRoot)) throw new Error("Skill permission root escapes the captured required workspace.");
return catalog.filter((skill) => {
if (!sandbox?.enabled) return resolveLocalPathFromRootsSync({
filePath: skill.source.filePath,
roots: [requiredRoot],
requireFile: true
}) !== null;
const resolved = sandbox.fsBridge?.resolvePath({
filePath: skill.location,
cwd: sandbox.containerWorkdir
});
return resolved?.hostPath !== void 0 && isPathInside$1(requiredRoot, resolved.hostPath);
}).map((skill) => {
const entry = Object.assign({}, skill);
entry.source = { filePath: skill.source.filePath };
entry.reader = async ({ location, signal }) => {
params.assertCurrent();
signal?.throwIfAborted();
const maxBytes = skill.promptListed ? Number.MAX_SAFE_INTEGER : MAX_SKILL_INSTRUCTION_BYTES;
let content;
if (sandbox?.enabled) {
if (!sandbox.fsBridge?.readFileWithSource) throw new Error("Sandbox skill reads require a source-aware filesystem bridge.");
const result = await sandbox.fsBridge.readFileWithSource({
filePath: location,
cwd: sandbox.containerWorkdir,
signal,
maxBytes
});
if (result.workspaceRelativePath === void 0 || !isPathInside$1(requiredRoot, path.resolve(sandbox.workspaceDir, result.workspaceRelativePath))) throw new Error("Skill instructions escape the captured required workspace.");
content = result.data;
} else {
const result = await readLocalFileFromRoots({
filePath: location,
roots: [requiredRoot],
hardlinks: "reject",
symlinks: "follow-within-root",
maxBytes
});
if (!result) throw new Error("Skill instructions escape the captured required workspace.");
content = result.buffer;
}
params.assertCurrent();
signal?.throwIfAborted();
return content.toString("utf8");
};
return entry;
});
};
}
//#endregion
//#region src/agents/harness/host-source-authority.ts
/** Keep the original run and caller predicates attached to every host capability. */
function bindHarnessHostSourceAuthority(params) {
const { attempt, sourceCaller, inactiveError } = params;
const operationalRunInstance = attempt.admittedRunContext.operationalRunInstance;
const admittedSource = captureAdmittedRunActiveAssertion(attempt.admittedRunContext, params.delegatedAuthority);
const assertAdmitted = composeSessionSourceAssertion([admittedSource], (assertSource) => {
if (!params.isActive() || !admittedSource || attempt.admittedRunContext.operationalRunInstance !== operationalRunInstance) throw inactiveError("agent harness host capability is no longer active");
try {
assertSource();
} catch {
throw inactiveError("agent harness host capability is no longer active");
}
if (!params.isGatewayCurrent()) throw inactiveError("agent harness host capability is no longer active");
});
const receipt = sourceCaller?.receiptAuthority;
const assertReceipt = receipt && captureGatewayToolReceiptAssertion(receipt, "agent harness host capability lost its source execution claim");
const assertCaller = composeSessionSourceAssertion([captureExternalSessionCommitGuard(assertReceipt)], (assertSource) => {
if (sourceCaller && (sourceCaller.agentId !== attempt.agentId || sourceCaller.sessionKey !== attempt.sessionKey) || sourceCaller?.workerTurnClaim && (sourceCaller.workerTurnClaim.sessionId !== attempt.sessionId || sourceCaller.workerTurnClaim.runId !== attempt.runId) || sourceCaller?.workerTurnClaim && !receipt) throw new Error("agent harness host capability lost its source execution claim");
assertSource();
});
return composeSessionSourceAssertion([assertAdmitted, assertCaller]);
}
/** Native delegation cannot select a person, so its live turn must remain unambiguous. */
function bindHarnessNativeSpawnAuthority(participants, assertActive) {
return participants ? () => {
assertActive();
participants.resolve()?.assertCurrent();
} : void 0;
}
/** Acquires original-source model authority while the issuing host is active. */
function bindHarnessModelExecution(admittedRunContext, model, assertActive) {
assertActive();
return bindOperatorModelExecution(readAdmittedRunOperatorAuthority(admittedRunContext), model);
}
const retainedSources = resolveGlobalSingleton(Symbol.for("openclaw.harness.retainedSources"), () => /* @__PURE__ */ new Set());
registerAgentEventLifecycleRotationHandler("harness-retained-sources", () => {
const retiring = [...retainedSources];
retainedSources.clear();
for (const controller of retiring) controller.abort(/* @__PURE__ */ new Error("agent harness retained source is no longer active"));
});
/** Transfers original-source custody while the issuing foreground host is still live. */
function retainHarnessSource(admittedRunContext, assertActive, nativeModelPolicySupported = false) {
assertActive();
const lifecycleGeneration = getAgentRunLifecycleGeneration();
const source = readAdmittedRunOperatorAuthority(admittedRunContext);
if (!source) return;
const modelExecution = nativeModelPolicySupported ? void 0 : bindOperatorModelExecution(source, void 0);
const release = nativeModelPolicySupported ? source.retain?.() : modelExecution?.release;
const assertSourceCurrent = () => {
if (nativeModelPolicySupported) source.assertCurrent();
else modelExecution?.assertCurrent();
};
try {
assertActive();
assertSourceCurrent();
assertActive();
} catch (error) {
release?.();
throw error;
}
let released = false;
let modelLifetime;
const lifecycle = new AbortController();
retainedSources.add(lifecycle);
const authoritySignal = modelExecution?.signal ?? source.signal;
const signal = authoritySignal ? AbortSignal.any([authoritySignal, lifecycle.signal]) : lifecycle.signal;
const assertRetained = () => {
if (released || getAgentRunLifecycleGeneration() !== lifecycleGeneration) throw new Error("agent harness retained source is no longer active");
signal.throwIfAborted();
};
const assertCurrent = () => {
assertRetained();
assertSourceCurrent();
assertRetained();
};
return Object.freeze({
signal,
assertCurrent,
get modelPolicyRequired() {
assertCurrent();
const required = source.modelPolicy !== void 0;
assertCurrent();
return required;
},
get sourceIdentity() {
assertCurrent();
const identity = source.source;
assertCurrent();
return identity;
},
bindModelExecution: (model) => {
assertCurrent();
const binding = bindOperatorModelExecution(source, model);
if (!binding) return;
const assertBindingCurrent = () => {
binding.assertCurrent();
assertRetained();
};
try {
assertBindingCurrent();
} catch (error) {
binding.release();
throw error;
}
modelLifetime ??= new AbortController();
return {
signal: AbortSignal.any([
signal,
modelLifetime.signal,
binding.signal
]),
assertCurrent: assertBindingCurrent,
release: binding.release
};
},
release: () => {
if (!released) {
released = true;
retainedSources.delete(lifecycle);
modelLifetime?.abort(/* @__PURE__ */ new Error("agent harness retained source is no longer active"));
release?.();
}
}
});
}
function assertCompactionSource(source) {
if (!source || !Object.hasOwn(source, "operatorAuthority")) throw new Error("Compaction requires its original host source authority");
source.assertActive();
if (source.operatorAuthority !== void 0) {
assertAdmittedRunOperatorAuthority(source.operatorAuthority);
source.operatorAuthority.assertCurrent();
}
}
/** Retains the existing issuer through queueing; the compaction work owner releases it. */
function retainAgentHarnessCompactionSource(source) {
assertCompactionSource(source);
const release = source.operatorAuthority?.retain?.();
try {
assertCompactionSource(source);
} catch (error) {
release?.();
throw error;
}
let released = false;
return () => {
if (!released) {
released = true;
release?.();
}
};
}
//#endregion
//#region src/agents/harness/host-trajectory.ts
/** Keeps trajectory callbacks bound to the exact foreground host lifetime. */
function bindHarnessTrajectory(recorder, assertActive) {
return Object.freeze({
recordEvent: (type, data) => {
assertActive();
recorder.recordEvent(type, data);
},
flush: async () => {
assertActive();
await recorder.flush();
assertActive();
}
});
}
//#endregion
//#region src/agents/harness/node-execution-authority.ts
/** Full is admitted host authority, narrowed to one placement claim, never a request flag. */
function createSessionNodeAuthorities(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
};
const assertRequestCurrent = (request) => {
if (request.source === "session-full" && (!admittedFull || !requiredNodeCommands.has(request.command))) throw new Error("admitted node execution authority does not cover this command");
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
});
};
const invokeWithSessionNodeAuthority = async (request, invoke) => {
if (request.source === "session-full" && (!admittedFull || !requiredNodeCommands.has(request.command))) return;
const assertCurrent = () => assertRequestCurrent(request);
assertCurrent();
const result = await invoke(assertCurrent, signal);
assertCurrent();
return result;
};
return {
invokeWithSessionNodeAuthority,
nodePlacementGrantAuthority: {
agentId: session.agentId,
sessionKey: attempt.sessionKey,
runId: attempt.runId,
assertCurrent: (request) => assertRequestCurrent({
...request,
source: "human-approved"
})
}
};
}
//#endregion
//#region src/agents/harness/host-capability.ts
/** Creates a closure-bound capability before plugin invocation. */
function createAgentHarnessHostCapabilities(params) {
const attempt = params.attempt;
const runtimePluginToolGrant = attempt.runtimePluginToolGrant ? Object.freeze({
pluginId: attempt.runtimePluginToolGrant.pluginId,
toolNames: Object.freeze([...attempt.runtimePluginToolGrant.toolNames])
}) : void 0;
const githubPublicationAvailable = attempt.githubPublicationAvailable;
const workSignal = getAsyncWorkSignal();
const attemptSignal = attempt.abortSignal;
const installationTarget = getInstallationTarget();
const { sessionKey, onAgentEvent } = attempt;
const requiredNodeCommands = new Set(params.requiredNodeCommands);
const nativeModelPolicySupported = params.nativeModelPolicySupport === "exact";
const operationalRunInstance = attempt.admittedRunContext.operationalRunInstance;
const delegatedAuthority = getAdmittedRunDelegatedAuthority(attempt.admittedRunContext);
const requesterProfileId = readAdmittedRunOperatorAuthority(attempt.admittedRunContext)?.profileId;
if (!delegatedAuthority) throw new Error("agent harness host capability requires active admitted run authority");
const { lifecycleGeneration } = delegatedAuthority;
const { runId } = delegatedAuthority.operationalRunInstance;
const coreTtsToolResults = /* @__PURE__ */ new WeakSet();
let active = true;
const capabilityAbortController = new AbortController();
const bindAbortSignal = (signal) => signal ? AbortSignal.any([signal, capabilityAbortController.signal]) : capabilityAbortController.signal;
const inheritedCaller = getGatewayToolCallerIdentity();
const sourceCaller = inheritedCaller?.operationalRunInstance === operationalRunInstance ? inheritedCaller : void 0;
let personalToolParticipants = sourceCaller?.personalToolParticipants;
const inactiveError = (message) => {
throwAgentRunRestartAbortReason(attemptSignal?.aborted ? attemptSignal.reason : workSignal?.reason);
return new Error(message);
};
const boundGatewayContext = getGatewayContextResolver(attempt.admittedRunContext);
const assertActive = bindHarnessHostSourceAuthority({
attempt,
delegatedAuthority,
sourceCaller,
isActive: () => active,
isGatewayCurrent: () => !boundGatewayContext || callerIdentity?.gatewayContextResolver?.() !== void 0,
inactiveError
});
const callerIdentity = createAdmittedGatewayToolCallerIdentity({
admittedRunContext: attempt.admittedRunContext,
receiptAuthority: assertActive,
approvalSignals: [capabilityAbortController.signal, ...attemptSignal ? [attemptSignal] : []],
agentId: attempt.agentId,
sessionKey: attempt.sessionKey,
turnSourceChannel: attempt.messageChannel ?? attempt.messageProvider,
turnSourceTo: attempt.currentMessagingTarget ?? attempt.currentChannelId,
turnSourceAccountId: attempt.agentAccountId,
turnSourceThreadId: attempt.currentThreadTs
});
const observeCoreTtsToolResult = (result) => {
if (typeof result === "object" && result !== null && getCoreTtsToolResultMediaUrls(result)) coreTtsToolResults.add(result);
};
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 ? cloneHostSnapshot(attempt.config) : void 0;
const hostSandboxEnabled = attempt.sandbox?.enabled === true;
const requiredWorkspace = captureRequiredWorkspaceToolFloor(attempt, params.pluginId, config);
const capturedWorkspaceOptions = requiredWorkspace?.apply();
const media = bindHarnessMedia({
attempt,
config,
assertActive,
signal: capabilityAbortController.signal
});
const recorder = attempt.userTurnTranscriptRecorder;
const sessionTarget = attempt.sessionTarget ? cloneHostSnapshot(attempt.sessionTarget) : void 0;
const annotateCurrentUserTurn = attempt.userTurnTranscriptRecorder && attempt.sessionTarget && attempt.agentId && attempt.sessionId && attempt.sessionKey && attempt.sessionTarget.storePath && !attempt.suppressNextUserMessagePersistence && attempt.trigger !== "memory" ? bindUserTurnTranscriptAnnotation({
recorder: attempt.userTurnTranscriptRecorder,
target: {
...attempt.sessionTarget,
agentId: attempt.agentId,
sessionId: attempt.sessionId,
sessionKey: attempt.sessionKey,
storePath: attempt.sessionTarget.storePath
},
runId: attempt.runId,
config,
abortSignal: bindAbortSignal(attempt.abortSignal),
assertCurrent: () => {
assertActive();
if (attempt.userTurnTranscriptRecorder !== recorder || !isDeepStrictEqual(attempt.sessionTarget, sessionTarget) || sessionTarget?.agentId !== void 0 && sessionTarget.agentId !== attempt.agentId || sessionTarget?.sessionId !== void 0 && sessionTarget.sessionId !== attempt.sessionId || sessionTarget?.sessionKey !== void 0 && sessionTarget.sessionKey !== attempt.sessionKey) throw new Error("native prompt annotation lost its source execution claim");
}
}) : void 0;
const skillsSnapshot = attempt.skillsSnapshot ? cloneHostSnapshot(attempt.skillsSnapshot) : void 0;
const getInstalledSkills = bindHostSkillCatalog({
snapshot: skillsSnapshot,
workspaceDir: capturedWorkspaceOptions?.workspaceDir ?? attempt.bootstrapWorkspaceDir ?? attempt.workspaceDir ?? attempt.cwd ?? process.cwd(),
sandbox: requiredWorkspace ? capturedWorkspaceOptions?.sandbox : attempt.sandbox,
requiredRoot: requiredWorkspace?.root,
readable: attempt.operation !== "settled-tool-finalization" && (!attempt.toolExecutionAllow || isToolExecutionAllowed(attempt.toolExecutionAllow, "read")),
assertCurrent: assertActive
});
const preparedRunEnvironment = prepareAgentHarnessEnvironment({
config,
agentId: attempt.agentId,
sessionKey: attempt.sessionKey,
sandboxAgentId: attempt.sandboxAgentId,
installationTarget
});
const skillUsagePaths = attempt.sandbox?.skillUsagePaths ? cloneHostSnapshot(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: cloneHostSnapshot(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, signal) => await withGatewayToolCallerIdentity(callerIdentity && signal ? {
...callerIdentity,
approvalSignals: [...callerIdentity.approvalSignals ?? [], signal]
} : callerIdentity, run);
const hookContextForOperation = (operation) => {
const cwd = operation?.cwd !== void 0 ? normalizeNativeOperationCwd(operation.cwd, hookContext.cwd) : void 0;
return cwd ? Object.freeze({
...hookContext,
cwd
}) : hookContext;
};
const runBeforeToolCallWithAssertion = async (assertCurrent, { nativeOperation, approvalMode, ...request }) => {
assertCurrent();
const hostApprovalMode = approvalMode === "defer" ? "defer" : "request";
const actionHookContext = hookContextForOperation(nativeOperation);
const result = await runBeforeToolCallHook({
...request,
approvalMode: hostApprovalMode,
ctx: actionHookContext
});
assertCurrent();
return result;
};
const runBeforeToolCall = async (request) => await withCaller(async () => await runBeforeToolCallWithAssertion(assertActive, request), request.signal);
registerAgentHarnessBeforeToolCallRetention(runBeforeToolCall, () => {
const recovery = retainAdmittedRunBeforeToolCallRecovery(attempt.admittedRunContext);
if (!recovery) return;
const assertRecoveryActive = () => {
if (attempt.abortSignal?.aborted || attempt.admittedRunContext.operationalRunInstance !== operationalRunInstance || boundGatewayContext && callerIdentity?.gatewayContextResolver?.() === void 0) throw inactiveError("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 bindTools = (tools, options, observeResult) => {
assertActive();
const boundAbortSignal = bindAbortSignal(attempt.abortSignal);
const bindingHookContext = hookContextForOperation(options);
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, observeResult));
};
const bindToolSurface = (tools, options) => bindTools(tools, options, () => {});
const bindModelExecution = nativeModelPolicySupported ? (model) => bindHarnessModelExecution(attempt.admittedRunContext, model, assertActive) : void 0;
const skillResourceSnapshot = (options) => !requiredWorkspace && !hostSandboxEnabled && !options?.sandbox?.enabled && options?.includeCoreTools !== false && options?.toolConstructionPlan?.includeBaseCodingTools !== false ? skillsSnapshot : void 0;
const toolConstructionInputs = (options, libraryEntries, assertCurrent = assertActive) => {
assertCurrent();
const effectiveOptions = {
...options,
...requiredWorkspace?.apply(options)
};
return {
options: {
...effectiveOptions,
githubPublicationAvailable,
runtimePluginToolGrant,
skillsSnapshot: options?.skillsSnapshot ?? skillsSnapshot,
installedSkills: getInstalledSkills(effectiveOptions.sandbox, effectiveOptions.sessionPermissionPolicy?.root),
skillUsagePaths: options?.skillUsagePaths ?? skillUsagePaths,
operationalRunInstance
},
skillReadResources: resolveSkillResourceCandidates(skillResourceSnapshot(options), libraryEntries)
};
};
const bindCreatedTools = (sourceTools, bindingOptions) => {
const tools = bindTools(sourceTools, bindingOptions, observeCoreTtsToolResult);
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;
};
const withToolConstructionScope = (run) => withAgentQuestionAnswerAuthority(resolveAgentQuestionAnswerAuthority(capabilities), () => withInstallationTarget(installationTarget, run));
const capabilities = Object.freeze({
kind: "agent-harness-host-capability",
version: 1,
assertActive,
get assertNativeSubagentSpawnAllowed() {
return bindHarnessNativeSpawnAuthority(personalToolParticipants, assertActive);
},
...bindModelExecution ? { bindModelExecution } : {},
retainSourceAuthority: () => retainHarnessSource(attempt.admittedRunContext, assertActive, nativeModelPolicySupported),
reportOutputTokens: (outputTokens) => {
assertActive();
const data = emitAgentRunOutputTokens({
runId,
lifecycleGeneration,
sessionKey,
outputTokens
});
if (data && onAgentEvent) runBestEffortCallback({
label: "usage agent event",
log,
callback: () => onAgentEvent({
stream: "usage",
data
})
});
},
...annotateCurrentUserTurn ? { annotateCurrentUserTurn } : {},
...media.capabilities,
...trajectoryRecorder ? { trajectory: bindHarnessTrajectory(trajectoryRecorder, assertActive) } : {},
preparedEnvironment: () => {
assertActive();
return preparedRunEnvironment;
},
activeComputerContext: () => {
assertActive();
return buildActiveNodeContextText(requesterProfileId);
},
bindToolSurface,
createToolSurface: (options, bindingOptions) => {
const inputs = toolConstructionInputs(options);
return bindCreatedTools(withToolConstructionScope(() => createOpenClawCodingToolsInternal(inputs.options, inputs.skillReadResources)), bindingOptions);
},
createToolSurfaceAsync: async (options, bindingOptions) => {
const librarySelections = skillResourceSnapshot(options)?.librarySelections ?? [];
const library = librarySelections.length ? await prepareHostSkillLibraryResources(librarySelections, assertActive) : void 0;
const inputs = toolConstructionInputs(options, library?.entries ?? [], library?.assertCurrent);
const sourceTools = await withToolConstructionScope(() => createOpenClawCodingToolsInternalAsync(inputs.options, inputs.skillReadResources, void 0, void 0, {
assertCurrent: library?.assertCurrent ?? assertActive,
signal: bindAbortSignal(attemptSignal)
}));
library?.assertPublicationCurrent();
return bindCreatedTools(sourceTools, bindingOptions);
},
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();
request.signal?.throwIfAborted();
const releaseMcpBinding = request.mcpTool && request.toolCallId && request.isMcpToolApprovalActive && attempt.agentId ? registerMcpToolApprovalBinding({
authority: delegatedAuthority,
agentId: attempt.agentId,
toolCallId: request.toolCallId,
...request.mcpTool,
isActive: () => {
assertActive();
return !request.signal?.aborted && request.isMcpToolApprovalActive();
}
}) : void 0;
try {
const result = await withCaller(async () => await withGatewayToolApprovalOwner(params.pluginId, async () => await callGatewayTool("plugin.approval.request", { timeoutMs: request.transportTimeoutMs ?? request.timeoutMs }, {
...formatHarnessApprovalPresentation(request),
...request.detail !== void 0 ? { detail: request.detail } : {},
severity: request.severity,
toolName: request.toolName,
toolCallId: request.toolCallId,
...request.mcpTool ? { mcpTool: request.mcpTool } : {},
timeoutMs: request.timeoutMs,
twoPhase: true,
...request.allowedDecisions ? { allowedDecisions: request.allowedDecisions } : {}
}, {
expectFinal: false,
requireAgentRuntimeIdentity: true,
signal: request.signal
})), request.signal);
assertActive();
request.signal?.throwIfAborted();
return result;
} finally {
releaseMcpBinding?.();
}
},
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 }), 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);
}
});
registerAgentHarnessTtsProvenanceTransferCapability({
hostCapabilities: capabilities,
ownerPluginId: params.pluginId,
transfer: (toolResult, attemptResult, eligibleMediaUrls) => {
assertActive();
if (typeof toolResult !== "object" || toolResult === null || !coreTtsToolResults.has(toolResult)) return attemptResult;
return transferCoreTtsToolResultProvenance(toolResult, attemptResult, eligibleMediaUrls, operationalRunInstance);
}
});
return {
capabilities,
setInputAttachmentReadAllowed: media.setInputAttachmentReadAllowed,
runWithScope: (run) => {
const preparedCaller = getGatewayToolCallerIdentity();
if (preparedCaller?.operationalRunInstance === operationalRunInstance) {
personalToolParticipants ??= preparedCaller.personalToolParticipants;
if (callerIdentity && personalToolParticipants) callerIdentity.personalToolParticipants = personalToolParticipants;
}
const nodeAuthorities = createSessionNodeAuthorities(attempt, params.pluginId, requiredNodeCommands, assertActive, bindAbortSignal(attempt.abortSignal));
return withPluginRuntimeGatewayRequestScope({
isWebchatConnect: () => false,
...getPluginRuntimeGatewayRequestScope(),
...nodeAuthorities
}, run);
},
close: () => {
if (!active) return;
active = false;
capabilityAbortController.abort();
}
};
}
//#endregion
export { assertCompactionSource as n, retainAgentHarnessCompactionSource as r, createAgentHarnessHostCapabilities as t };