mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-24 22:43:04 +00:00
fix(telegram): join inline reply prompt
This commit is contained in:
@@ -362,7 +362,7 @@ import {
|
||||
shouldPreemptivelyCompactBeforePrompt,
|
||||
} from "./preemptive-compaction.js";
|
||||
import {
|
||||
buildCurrentTurnPromptContextPrefix,
|
||||
buildCurrentTurnPrompt,
|
||||
buildRuntimeContextSystemContext,
|
||||
queueRuntimeContextForNextTurn,
|
||||
resolveRuntimeContextPromptParts,
|
||||
@@ -3114,12 +3114,10 @@ export async function runEmbeddedAttempt(
|
||||
effectivePrompt,
|
||||
transcriptPrompt: effectiveTranscriptPrompt,
|
||||
});
|
||||
const currentTurnPromptContextPrefix = promptSubmission.runtimeOnly
|
||||
? ""
|
||||
: buildCurrentTurnPromptContextPrefix(params.currentTurnContext);
|
||||
const promptForModel = [currentTurnPromptContextPrefix, promptSubmission.prompt]
|
||||
.filter(Boolean)
|
||||
.join("\n\n");
|
||||
const promptForModel = buildCurrentTurnPrompt({
|
||||
context: promptSubmission.runtimeOnly ? undefined : params.currentTurnContext,
|
||||
prompt: promptSubmission.prompt,
|
||||
});
|
||||
const runtimeSystemContext = promptSubmission.runtimeSystemContext?.trim();
|
||||
if (promptSubmission.runtimeOnly && runtimeSystemContext) {
|
||||
const runtimeSystemPrompt = composeSystemPromptWithHookContext({
|
||||
|
||||
@@ -30,6 +30,7 @@ export type EmbeddedRunTrigger = "cron" | "heartbeat" | "manual" | "memory" | "o
|
||||
|
||||
export type CurrentTurnPromptContext = {
|
||||
text: string;
|
||||
promptJoiner?: "\n\n" | "\n" | " ";
|
||||
};
|
||||
|
||||
export type RunEmbeddedPiAgentParams = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
buildCurrentTurnPrompt,
|
||||
buildCurrentTurnPromptContextPrefix,
|
||||
buildRuntimeContextSystemContext,
|
||||
queueRuntimeContextForNextTurn,
|
||||
@@ -81,6 +82,22 @@ describe("runtime context prompt submission", () => {
|
||||
expect(buildCurrentTurnPromptContextPrefix({ text: " " })).toBe("");
|
||||
});
|
||||
|
||||
it("joins current-turn context and prompt with the requested separator", () => {
|
||||
expect(
|
||||
buildCurrentTurnPrompt({
|
||||
context: { text: "Current message:\n#34975 obviyus:", promptJoiner: " " },
|
||||
prompt: "What do you mean hidden?",
|
||||
}),
|
||||
).toBe("Current message:\n#34975 obviyus: What do you mean hidden?");
|
||||
|
||||
expect(
|
||||
buildCurrentTurnPrompt({
|
||||
context: { text: "Conversation context:" },
|
||||
prompt: "visible ask",
|
||||
}),
|
||||
).toBe("Conversation context:\n\nvisible ask");
|
||||
});
|
||||
|
||||
it("queues runtime context as a hidden next-turn custom message", async () => {
|
||||
const sentMessages: Array<{ content: string }> = [];
|
||||
const sendCustomMessage = vi.fn(async (message: { content: string }) => {
|
||||
|
||||
@@ -34,6 +34,20 @@ export function buildCurrentTurnPromptContextPrefix(
|
||||
return context?.text.trim() ?? "";
|
||||
}
|
||||
|
||||
export function buildCurrentTurnPrompt(params: {
|
||||
context: CurrentTurnPromptContext | undefined;
|
||||
prompt: string;
|
||||
}): string {
|
||||
const prefix = buildCurrentTurnPromptContextPrefix(params.context);
|
||||
if (!prefix) {
|
||||
return params.prompt;
|
||||
}
|
||||
if (!params.prompt) {
|
||||
return prefix;
|
||||
}
|
||||
return [prefix, params.prompt].join(params.context?.promptJoiner ?? "\n\n");
|
||||
}
|
||||
|
||||
function removeLastPromptOccurrence(text: string, prompt: string): string | null {
|
||||
const index = text.lastIndexOf(prompt);
|
||||
if (index === -1) {
|
||||
|
||||
@@ -99,6 +99,7 @@ vi.mock("./groups.js", () => ({
|
||||
vi.mock("./inbound-meta.js", () => ({
|
||||
buildInboundMetaSystemPrompt: vi.fn().mockReturnValue(""),
|
||||
buildInboundUserContextPrefix: vi.fn().mockReturnValue(""),
|
||||
resolveInboundUserContextPromptJoiner: vi.fn().mockReturnValue(undefined),
|
||||
}));
|
||||
|
||||
vi.mock("./queue/settings-runtime.js", () => ({
|
||||
@@ -133,6 +134,7 @@ let resolveTypingMode: typeof import("./typing-mode.js").resolveTypingMode;
|
||||
let buildDirectChatContext: typeof import("./groups.js").buildDirectChatContext;
|
||||
let buildGroupChatContext: typeof import("./groups.js").buildGroupChatContext;
|
||||
let buildInboundUserContextPrefix: typeof import("./inbound-meta.js").buildInboundUserContextPrefix;
|
||||
let resolveInboundUserContextPromptJoiner: typeof import("./inbound-meta.js").resolveInboundUserContextPromptJoiner;
|
||||
let getActiveReplyRunCount: typeof import("./reply-run-registry.js").getActiveReplyRunCount;
|
||||
let replyRunTesting: typeof import("./reply-run-registry.js").__testing;
|
||||
let loadScopeCounter = 0;
|
||||
@@ -252,7 +254,8 @@ describe("runPreparedReply media-only handling", () => {
|
||||
({ drainFormattedSystemEvents } = await import("./session-system-events.js"));
|
||||
({ resolveTypingMode } = await import("./typing-mode.js"));
|
||||
({ buildDirectChatContext, buildGroupChatContext } = await import("./groups.js"));
|
||||
({ buildInboundUserContextPrefix } = await import("./inbound-meta.js"));
|
||||
({ buildInboundUserContextPrefix, resolveInboundUserContextPromptJoiner } =
|
||||
await import("./inbound-meta.js"));
|
||||
({ __testing: replyRunTesting, getActiveReplyRunCount } =
|
||||
await import("./reply-run-registry.js"));
|
||||
});
|
||||
@@ -1142,6 +1145,7 @@ describe("runPreparedReply media-only handling", () => {
|
||||
vi.mocked(buildInboundUserContextPrefix).mockReturnValueOnce(
|
||||
["Current message:", '[Replying to: "quoted status body"]', "#34974 obviyus:"].join("\n"),
|
||||
);
|
||||
vi.mocked(resolveInboundUserContextPromptJoiner).mockReturnValueOnce(" ");
|
||||
|
||||
await runPreparedReply(
|
||||
baseParams({
|
||||
@@ -1172,6 +1176,7 @@ describe("runPreparedReply media-only handling", () => {
|
||||
expect(call?.transcriptCommandBody).toBe("what does this mean?");
|
||||
expect(call?.followupRun.prompt).toContain("what does this mean?");
|
||||
expect(call?.followupRun.transcriptPrompt).toBe("what does this mean?");
|
||||
expect(call?.followupRun.currentTurnContext?.promptJoiner).toBe(" ");
|
||||
expect(call?.followupRun.currentTurnContext?.text).toContain("Current message:");
|
||||
expect(call?.followupRun.currentTurnContext?.text).toContain(
|
||||
'[Replying to: "quoted status body"]',
|
||||
|
||||
@@ -60,7 +60,11 @@ import {
|
||||
resolveGroupSilentReplyBehavior,
|
||||
} from "./groups.js";
|
||||
import { hasInboundMedia } from "./inbound-media.js";
|
||||
import { buildInboundMetaSystemPrompt, buildInboundUserContextPrefix } from "./inbound-meta.js";
|
||||
import {
|
||||
buildInboundMetaSystemPrompt,
|
||||
buildInboundUserContextPrefix,
|
||||
resolveInboundUserContextPromptJoiner,
|
||||
} from "./inbound-meta.js";
|
||||
import type { createModelSelectionState } from "./model-selection.js";
|
||||
import { resolveOriginMessageProvider } from "./origin-routing.js";
|
||||
import { buildReplyPromptBodies } from "./prompt-prelude.js";
|
||||
@@ -750,7 +754,12 @@ export async function runPreparedReply(
|
||||
() => rebuildPromptBodies(),
|
||||
);
|
||||
const currentTurnContext: CurrentTurnPromptContext | undefined =
|
||||
!isBareSessionReset && inboundUserContext.trim() ? { text: inboundUserContext } : undefined;
|
||||
!isBareSessionReset && inboundUserContext.trim()
|
||||
? {
|
||||
text: inboundUserContext,
|
||||
promptJoiner: resolveInboundUserContextPromptJoiner(sessionCtx),
|
||||
}
|
||||
: undefined;
|
||||
if (!resolvedThinkLevel) {
|
||||
resolvedThinkLevel = await modelState.resolveDefaultThinkingLevel();
|
||||
}
|
||||
|
||||
@@ -321,6 +321,10 @@ function formatTelegramCurrentMessageContext(ctx: TemplateContext): string | und
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
export function resolveInboundUserContextPromptJoiner(ctx: TemplateContext): " " | undefined {
|
||||
return formatTelegramCurrentMessageContext(ctx) ? " " : undefined;
|
||||
}
|
||||
|
||||
function formatConversationTimestamp(
|
||||
value: unknown,
|
||||
envelope?: EnvelopeFormatOptions,
|
||||
|
||||
Reference in New Issue
Block a user