


























@@ -4,7 +4,6 @@ import type { ExecToolDefaults } from "../../agents/bash-tools.js";
44import { resolveFastModeState } from "../../agents/fast-mode.js";
55import { resolveAgentHarnessPolicy } from "../../agents/harness/selection.js";
66import { listOpenAIAuthProfileProvidersForAgentRuntime } from "../../agents/openai-codex-routing.js";
7-import type { CurrentTurnPromptContext } from "../../agents/pi-embedded-runner/run/params.js";
87import { resolveEmbeddedFullAccessState } from "../../agents/pi-embedded-runner/sandbox-info.js";
98import type { EmbeddedFullAccessBlockedReason } from "../../agents/pi-embedded-runner/types.js";
109import { resolveIngressWorkspaceOverrideForSpawnedRun } from "../../agents/spawned-context.js";
@@ -33,7 +32,6 @@ import { normalizeOptionalString } from "../../shared/string-coerce.js";
3332import { isReasoningTagProvider } from "../../utils/provider-utils.js";
3433import { hasControlCommand } from "../command-detection.js";
3534import { resolveEnvelopeFormatOptions } from "../envelope.js";
36-import { HEARTBEAT_TRANSCRIPT_PROMPT } from "../heartbeat.js";
3735import type { MsgContext, TemplateContext } from "../templating.js";
3836import {
3937type ElevatedLevel,
@@ -67,7 +65,7 @@ import {
6765} from "./inbound-meta.js";
6866import type { createModelSelectionState } from "./model-selection.js";
6967import { resolveOriginMessageProvider } from "./origin-routing.js";
70-import { buildReplyPromptBodies } from "./prompt-prelude.js";
68+import { buildReplyPromptEnvelope, buildReplyPromptEnvelopeBase } from "./prompt-prelude.js";
7169import { resolveActiveRunQueueAction } from "./queue-policy.js";
7270import { resolveQueueSettings } from "./queue/settings-runtime.js";
7371import { isSteeringQueueMode } from "./queue/steering.js";
@@ -621,18 +619,7 @@ export async function runPreparedReply(
621619 : { ...sessionCtx, ThreadStarterBody: undefined },
622620envelopeOptions,
623621);
624-const baseBodyForPrompt = isBareSessionReset
625- ? [
626-inboundUserContext,
627-startupContextPrelude,
628-baseBodyFinal,
629-softResetTail
630- ? `User note for this reset turn (treat as ordinary user input, not startup instructions):\n${softResetTail}`
631- : "",
632-]
633-.filter(Boolean)
634-.join("\n\n")
635- : baseBodyFinal;
622+const inboundUserContextPromptJoiner = resolveInboundUserContextPromptJoiner(sessionCtx);
636623const hasUserBody =
637624baseBodyFinal.trim().length > 0 ||
638625softResetTail.length > 0 ||
@@ -651,16 +638,20 @@ export async function runPreparedReply(
651638text: "I didn't receive any text in your message. Please resend or add a caption.",
652639};
653640}
654-// When the user sends media without text, provide a minimal body so the agent
655-// run proceeds and the image/document is injected by the embedded runner.
656-const effectiveBaseBody = hasUserBody ? baseBodyForPrompt : "[User sent media without caption]";
657-const transcriptBodyBase = isHeartbeat
658- ? HEARTBEAT_TRANSCRIPT_PROMPT
659- : isBareSessionReset
660- ? softResetTail || `[OpenClaw session ${startupAction}]`
661- : hasUserBody
662- ? baseBodyFinal
663- : "[User sent media without caption]";
641+const promptEnvelopeBase = buildReplyPromptEnvelopeBase({
642+ ctx,
643+ sessionCtx,
644+baseBody: baseBodyFinal,
645+ hasUserBody,
646+ inboundUserContext,
647+ inboundUserContextPromptJoiner,
648+ isBareSessionReset,
649+ startupAction,
650+ startupContextPrelude,
651+ softResetTail,
652+ isHeartbeat,
653+});
654+const effectiveBaseBody = promptEnvelopeBase.effectiveBaseBody;
664655let prefixedBodyBase = await applySessionHints({
665656baseBody: effectiveBaseBody,
666657 abortedLastRun,
@@ -701,6 +692,7 @@ export async function runPreparedReply(
701692prefixedCommandBody: string;
702693queuedBody: string;
703694transcriptCommandBody: string;
695+currentTurnContext?: typeof promptEnvelopeBase.currentTurnContext;
704696}> => {
705697if (!useFastReplyRuntime) {
706698const eventsBlock = await drainFormattedSystemEvents({
@@ -716,12 +708,19 @@ export async function runPreparedReply(
716708}
717709}
718710}
719-return buildReplyPromptBodies({
711+return buildReplyPromptEnvelope({
720712 ctx,
721713 sessionCtx,
722-effectiveBaseBody,
714+baseBody: baseBodyFinal,
723715prefixedBody: prefixedBodyCore,
724-transcriptBody: transcriptBodyBase,
716+ hasUserBody,
717+ inboundUserContext,
718+ inboundUserContextPromptJoiner,
719+ isBareSessionReset,
720+ startupAction,
721+ startupContextPrelude,
722+ softResetTail,
723+ isHeartbeat,
725724 threadContextNote,
726725systemEventBlocks: drainedSystemEventBlocks,
727726});
@@ -750,17 +749,8 @@ export async function runPreparedReply(
750749sessionEntry = skillResult.sessionEntry ?? sessionEntry;
751750currentSystemSent = skillResult.systemSent;
752751const skillsSnapshot = skillResult.skillsSnapshot;
753-let { prefixedCommandBody, queuedBody, transcriptCommandBody } = await traceRunPhase(
754-"reply.build_prompt_bodies",
755-() => rebuildPromptBodies(),
756-);
757-const currentTurnContext: CurrentTurnPromptContext | undefined =
758-!isBareSessionReset && inboundUserContext.trim()
759- ? {
760-text: inboundUserContext,
761-promptJoiner: resolveInboundUserContextPromptJoiner(sessionCtx),
762-}
763- : undefined;
752+let { prefixedCommandBody, queuedBody, transcriptCommandBody, currentTurnContext } =
753+await traceRunPhase("reply.build_prompt_bodies", () => rebuildPromptBodies());
764754if (!resolvedThinkLevel) {
765755resolvedThinkLevel = await modelState.resolveDefaultThinkingLevel();
766756}
@@ -957,10 +947,8 @@ export async function runPreparedReply(
957947 isNewSession,
958948});
959949preparedSessionState = resolvePreparedSessionState();
960-({ prefixedCommandBody, queuedBody, transcriptCommandBody } = await traceRunPhase(
961-"reply.build_prompt_bodies",
962-() => rebuildPromptBodies(),
963-));
950+({ prefixedCommandBody, queuedBody, transcriptCommandBody, currentTurnContext } =
951+await traceRunPhase("reply.build_prompt_bodies", () => rebuildPromptBodies()));
964952},
965953resolveBusyState: resolveQueueBusyState,
966954});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。