openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
126 lines (125 loc) • 7.21 kB
JavaScript
import { a as OPENCLAW_RUNTIME_EVENT_HEADER, i as OPENCLAW_RUNTIME_CONTEXT_NOTICE, n as INTERNAL_RUNTIME_CONTEXT_END, r as OPENCLAW_RUNTIME_CONTEXT_CUSTOM_TYPE, s as extractInternalRuntimeContext, t as INTERNAL_RUNTIME_CONTEXT_BEGIN } from "./internal-runtime-context-UgZVJlox.js";
//#region src/agents/embedded-agent-runner/run/runtime-context-prompt.ts
/**
* Builds runtime context prompt fragments and custom session messages.
*/
const OPENCLAW_RUNTIME_EVENT_USER_PROMPT = "Continue the OpenClaw runtime event.";
/** Combines inbound context and the current prompt using the channel-provided joiner. */
function buildCurrentInboundPrompt(params) {
const prefix = (params.preferResumableText === true ? params.context?.resumableText ?? params.context?.text : params.context?.text)?.trim() ?? "";
if (!prefix) return params.prompt;
if (!params.prompt) return prefix;
return [prefix, params.prompt].join(params.context?.promptJoiner ?? "\n\n");
}
function splitLastPromptOccurrence(text, prompt) {
const index = text.lastIndexOf(prompt);
if (index === -1) return null;
return {
before: text.slice(0, index),
after: text.slice(index + prompt.length)
};
}
function replacePromptOccurrenceWithinHookBounds(params) {
if (!params.promptBeforeHooks) return null;
const prependIndex = params.prependContext ? params.text.indexOf(params.prependContext) : -1;
if (params.prependContext && prependIndex === -1) return null;
const searchStart = prependIndex === -1 ? 0 : prependIndex + params.prependContext.length;
const appendIndex = params.appendContext ? params.text.lastIndexOf(params.appendContext) : -1;
if (params.appendContext && appendIndex < searchStart) return null;
const searchEnd = appendIndex === -1 ? params.text.length : appendIndex;
const occurrenceIndex = params.text.lastIndexOf(params.promptBeforeHooks, searchEnd - params.promptBeforeHooks.length);
if (occurrenceIndex < searchStart || occurrenceIndex + params.promptBeforeHooks.length > searchEnd) return null;
return `${params.text.slice(0, occurrenceIndex)}${params.transcriptPrompt}${params.text.slice(occurrenceIndex + params.promptBeforeHooks.length)}`;
}
/**
* Separates user-authored prompt text from hidden runtime context. Transcript
* prompt stays user-visible; model prompt may carry runtime-only additions that
* should be delivered as hidden context instead of persisted as user text.
*/
function resolveRuntimeContextPromptParts(params) {
const transcriptPrompt = params.transcriptPrompt;
const shouldExtractInternalRuntimeContext = transcriptPrompt !== void 0;
const extracted = shouldExtractInternalRuntimeContext ? extractInternalRuntimeContext(params.effectivePrompt) : { text: params.effectivePrompt };
const modelPrompt = params.modelPrompt === void 0 ? void 0 : shouldExtractInternalRuntimeContext ? extractInternalRuntimeContext(params.modelPrompt) : { text: params.modelPrompt };
const modelPromptBuildContext = params.modelPromptBuildContext ? {
promptBeforeHooks: extractInternalRuntimeContext(params.modelPromptBuildContext.promptBeforeHooks).text,
transcriptPromptBeforeTransforms: extractInternalRuntimeContext(params.modelPromptBuildContext.transcriptPromptBeforeTransforms).text,
promptBeforeAnnotation: extractInternalRuntimeContext(params.modelPromptBuildContext.promptBeforeAnnotation).text,
prependContext: extractInternalRuntimeContext(params.modelPromptBuildContext.prependContext).text,
appendContext: extractInternalRuntimeContext(params.modelPromptBuildContext.appendContext).text
} : void 0;
const modelPromptText = modelPrompt?.text ?? transcriptPrompt ?? extracted.text;
const prompt = transcriptPrompt ?? extracted.text;
if (!prompt.trim() && params.emptyTranscriptMode === "model-prompt") return {
prompt: extracted.text,
...modelPromptText.trim() && modelPromptText !== extracted.text ? { modelPrompt: modelPromptText } : {},
...extracted.runtimeContext ? { runtimeContext: extracted.runtimeContext } : {}
};
const sourcePromptParts = modelPromptBuildContext ? splitLastPromptOccurrence(modelPromptBuildContext.promptBeforeHooks, modelPromptBuildContext.transcriptPromptBeforeTransforms) : void 0;
const outerPromptParts = modelPromptBuildContext ? splitLastPromptOccurrence(extracted.text, modelPromptBuildContext.promptBeforeAnnotation) : void 0;
const fallbackPromptParts = !modelPromptBuildContext ? modelPrompt ? splitLastPromptOccurrence(extracted.text, modelPrompt.text) ?? (transcriptPrompt ? splitLastPromptOccurrence(extracted.text, transcriptPrompt) : void 0) : transcriptPrompt ? splitLastPromptOccurrence(extracted.text, transcriptPrompt) : void 0 : void 0;
const runtimeContext = [[
outerPromptParts?.before,
sourcePromptParts?.before ?? fallbackPromptParts?.before,
sourcePromptParts?.after ?? fallbackPromptParts?.after,
outerPromptParts?.after
].map((part) => part?.trim()).filter((part) => Boolean(part)).join("\n\n"), extracted.runtimeContext].filter((value) => Boolean(value?.trim())).join("\n\n") || (!prompt.trim() ? extracted.text.trim() : void 0);
if (!prompt.trim()) return runtimeContext ? {
prompt: OPENCLAW_RUNTIME_EVENT_USER_PROMPT,
...modelPromptText.trim() && modelPromptText !== OPENCLAW_RUNTIME_EVENT_USER_PROMPT ? { modelPrompt: modelPromptText } : {},
runtimeContext,
runtimeOnly: true,
runtimeSystemContext: buildRuntimeContextMessageContent({
runtimeContext,
kind: "runtime-event"
})
} : {
prompt: "",
...modelPromptText ? { modelPrompt: modelPromptText } : {}
};
const returnModelPromptText = Boolean(sourcePromptParts?.before.trim() || sourcePromptParts?.after.trim()) && modelPromptBuildContext && modelPrompt ? replacePromptOccurrenceWithinHookBounds({
text: modelPromptText,
promptBeforeHooks: modelPromptBuildContext.promptBeforeHooks,
transcriptPrompt: modelPromptBuildContext.transcriptPromptBeforeTransforms,
prependContext: modelPromptBuildContext.prependContext,
appendContext: modelPromptBuildContext.appendContext
}) ?? modelPromptText : modelPromptText;
return {
prompt,
...returnModelPromptText.trim() && returnModelPromptText !== prompt ? { modelPrompt: returnModelPromptText } : {},
...runtimeContext ? { runtimeContext } : {}
};
}
function buildRuntimeContextMessageContent(params) {
return [
...params.kind === "runtime-event" ? [
OPENCLAW_RUNTIME_EVENT_HEADER,
OPENCLAW_RUNTIME_CONTEXT_NOTICE,
""
] : [],
INTERNAL_RUNTIME_CONTEXT_BEGIN,
params.runtimeContext,
INTERNAL_RUNTIME_CONTEXT_END
].join("\n");
}
/** Creates a non-displayed custom transcript message for runtime context, if any exists. */
function buildRuntimeContextCustomMessage(runtimeContext) {
const trimmedRuntimeContext = runtimeContext?.trim();
if (!trimmedRuntimeContext) return;
return {
role: "custom",
customType: OPENCLAW_RUNTIME_CONTEXT_CUSTOM_TYPE,
content: buildRuntimeContextMessageContent({
runtimeContext: trimmedRuntimeContext,
kind: "next-turn"
}),
display: false,
details: {
source: "openclaw-runtime-context",
runtimeContextCarrier: true
},
timestamp: Date.now()
};
}
//#endregion
export { buildRuntimeContextCustomMessage as n, resolveRuntimeContextPromptParts as r, buildCurrentInboundPrompt as t };