
























@@ -4,12 +4,15 @@ export const INTERNAL_RUNTIME_CONTEXT_END = "<<<END_OPENCLAW_INTERNAL_CONTEXT>>>
44const ESCAPED_INTERNAL_RUNTIME_CONTEXT_BEGIN = "[[OPENCLAW_INTERNAL_CONTEXT_BEGIN]]";
55const ESCAPED_INTERNAL_RUNTIME_CONTEXT_END = "[[OPENCLAW_INTERNAL_CONTEXT_END]]";
667+export const OPENCLAW_RUNTIME_CONTEXT_NOTICE =
8+"This context is runtime-generated, not user-authored. Keep internal details private.";
9+export const OPENCLAW_NEXT_TURN_RUNTIME_CONTEXT_HEADER =
10+"OpenClaw runtime context for the immediately preceding user message.";
11+export const OPENCLAW_RUNTIME_EVENT_HEADER = "OpenClaw runtime event.";
12+export const OPENCLAW_RUNTIME_CONTEXT_CUSTOM_TYPE = "openclaw.runtime-context";
13+714const LEGACY_INTERNAL_CONTEXT_HEADER =
8-[
9-"OpenClaw runtime context (internal):",
10-"This context is runtime-generated, not user-authored. Keep internal details private.",
11-"",
12-].join("\n") + "\n";
15+["OpenClaw runtime context (internal):", OPENCLAW_RUNTIME_CONTEXT_NOTICE, ""].join("\n") + "\n";
13161417const LEGACY_INTERNAL_EVENT_MARKER = "[Internal task completion event]";
1518const LEGACY_INTERNAL_EVENT_SEPARATOR = "\n\n---\n\n";
@@ -154,6 +157,42 @@ function stripLegacyInternalRuntimeContext(text: string): string {
154157}
155158}
156159160+function isRuntimeContextPromptHeader(line: string): boolean {
161+return (
162+line === OPENCLAW_NEXT_TURN_RUNTIME_CONTEXT_HEADER || line === OPENCLAW_RUNTIME_EVENT_HEADER
163+);
164+}
165+166+function stripRuntimeContextPromptPreface(text: string): string {
167+const lines = text.split(/\r?\n/);
168+let changed = false;
169+const output: string[] = [];
170+171+for (let index = 0; index < lines.length; index += 1) {
172+const line = lines[index] ?? "";
173+const nextLine = lines[index + 1] ?? "";
174+if (
175+isRuntimeContextPromptHeader(line.trim()) &&
176+nextLine.trim() === OPENCLAW_RUNTIME_CONTEXT_NOTICE
177+) {
178+changed = true;
179+index += 1;
180+while (index + 1 < lines.length && (lines[index + 1] ?? "").trim() === "") {
181+index += 1;
182+}
183+continue;
184+}
185+output.push(line);
186+}
187+188+return changed
189+ ? output
190+.join("\n")
191+.replace(/\n{3,}/g, "\n\n")
192+.trim()
193+ : text;
194+}
195+157196export function stripInternalRuntimeContext(text: string): string {
158197if (!text) {
159198return text;
@@ -163,7 +202,9 @@ export function stripInternalRuntimeContext(text: string): string {
163202INTERNAL_RUNTIME_CONTEXT_BEGIN,
164203INTERNAL_RUNTIME_CONTEXT_END,
165204);
166-return stripLegacyInternalRuntimeContext(withoutDelimitedBlocks);
205+return stripRuntimeContextPromptPreface(
206+stripLegacyInternalRuntimeContext(withoutDelimitedBlocks),
207+);
167208}
168209169210export function hasInternalRuntimeContext(text: string): boolean {
@@ -172,6 +213,27 @@ export function hasInternalRuntimeContext(text: string): boolean {
172213}
173214return (
174215findDelimitedTokenIndex(text, INTERNAL_RUNTIME_CONTEXT_BEGIN, 0) !== -1 ||
175-text.includes(LEGACY_INTERNAL_CONTEXT_HEADER)
216+text.includes(LEGACY_INTERNAL_CONTEXT_HEADER) ||
217+text.includes(
218+`${OPENCLAW_NEXT_TURN_RUNTIME_CONTEXT_HEADER}\n${OPENCLAW_RUNTIME_CONTEXT_NOTICE}`,
219+) ||
220+text.includes(`${OPENCLAW_RUNTIME_EVENT_HEADER}\n${OPENCLAW_RUNTIME_CONTEXT_NOTICE}`)
176221);
177222}
223+224+export function isOpenClawRuntimeContextCustomMessage(message: unknown): boolean {
225+if (!message || typeof message !== "object") {
226+return false;
227+}
228+const candidate = message as { role?: unknown; customType?: unknown };
229+return (
230+candidate.role === "custom" && candidate.customType === OPENCLAW_RUNTIME_CONTEXT_CUSTOM_TYPE
231+);
232+}
233+234+export function stripRuntimeContextCustomMessages<T>(messages: T[]): T[] {
235+if (!messages.some(isOpenClawRuntimeContextCustomMessage)) {
236+return messages;
237+}
238+return messages.filter((message) => !isOpenClawRuntimeContextCustomMessage(message));
239+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。