fix(telegram): join inline reply prompt

This commit is contained in:
Ayaan Zaidi
2026-05-11 09:18:33 +05:30
parent ea48d27cd7
commit 7337c3a9e9
7 changed files with 58 additions and 10 deletions

View File

@@ -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({

View File

@@ -30,6 +30,7 @@ export type EmbeddedRunTrigger = "cron" | "heartbeat" | "manual" | "memory" | "o
export type CurrentTurnPromptContext = {
text: string;
promptJoiner?: "\n\n" | "\n" | " ";
};
export type RunEmbeddedPiAgentParams = {

View File

@@ -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 }) => {

View File

@@ -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) {

View File

@@ -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"]',

View File

@@ -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();
}

View File

@@ -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,