Skip to content

Commit 45e36a2

Browse files
committed
fix(telegram): pass rich text prompts to cli backends
1 parent 5cb6f8a commit 45e36a2

4 files changed

Lines changed: 81 additions & 0 deletions

File tree

src/agents/cli-runner/helpers.system-prompt.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,21 @@ describe("buildCliAgentSystemPrompt", () => {
106106
expect(prompt).toContain("session=agent:main:telegram:direct:peer");
107107
expect(prompt).toContain("sessionId=session-123");
108108
});
109+
110+
it("includes Telegram rich text guidance for CLI final replies", () => {
111+
const prompt = buildCliAgentSystemPrompt({
112+
workspaceDir: "/tmp/openclaw",
113+
tools: [],
114+
modelDisplay: "anthropic/claude-opus-4-8",
115+
runtimeChannel: "telegram",
116+
runtimeChatType: "direct",
117+
runtimeCapabilities: ["richText"],
118+
});
119+
120+
expect(prompt).toContain("Telegram rich text is available");
121+
expect(prompt).toContain("headings, tables");
122+
expect(prompt).toContain("This is not legacy MarkdownV2/parse_mode");
123+
expect(prompt).toContain("channel=telegram");
124+
expect(prompt).not.toContain("### message tool");
125+
});
109126
});

src/agents/cli-runner/helpers.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
1616
import { isAcpRuntimeSpawnAvailable } from "../../acp/runtime/availability.js";
1717
import type { SourceReplyDeliveryMode } from "../../auto-reply/get-reply-options.types.js";
1818
import type { ThinkLevel } from "../../auto-reply/thinking.js";
19+
import type { ChatType } from "../../channels/chat-type.js";
1920
import type { CliBackendConfig } from "../../config/types.js";
2021
import type { OpenClawConfig } from "../../config/types.openclaw.js";
2122
import { privateFileStore } from "../../infra/private-file-store.js";
@@ -119,6 +120,9 @@ export function buildCliAgentSystemPrompt(params: {
119120
extraSystemPrompt?: string;
120121
sourceReplyDeliveryMode?: SourceReplyDeliveryMode;
121122
silentReplyPromptMode?: SilentReplyPromptMode;
123+
runtimeChannel?: string;
124+
runtimeChatType?: ChatType;
125+
runtimeCapabilities?: string[];
122126
ownerNumbers?: string[];
123127
heartbeatPrompt?: string;
124128
docsPath?: string;
@@ -152,6 +156,9 @@ export function buildCliAgentSystemPrompt(params: {
152156
model: params.modelDisplay,
153157
defaultModel: defaultModelLabel,
154158
shell: detectRuntimeShell(),
159+
channel: params.runtimeChannel,
160+
chatType: params.runtimeChatType,
161+
capabilities: params.runtimeCapabilities,
155162
},
156163
});
157164
return buildConfiguredAgentSystemPrompt({

src/agents/cli-runner/prepare.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import os from "node:os";
55
import path from "node:path";
66
import { CURRENT_SESSION_VERSION } from "openclaw/plugin-sdk/agent-sessions";
77
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
8+
import type { ChannelPlugin } from "../../channels/plugins/types.plugin.js";
89
import type { OpenClawConfig } from "../../config/types.openclaw.js";
910
import { registerLegacyContextEngine } from "../../context-engine/legacy.registration.js";
1011
import {
@@ -14,6 +15,11 @@ import {
1415
import type { ContextEngine } from "../../context-engine/types.js";
1516
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
1617
import { clearMemoryPluginState, registerMemoryPromptSection } from "../../plugins/memory-state.js";
18+
import { setActivePluginRegistry } from "../../plugins/runtime.js";
19+
import {
20+
createChannelTestPluginBase,
21+
createTestRegistry,
22+
} from "../../test-utils/channel-plugins.js";
1723
import { captureEnv, setTestEnvValue } from "../../test-utils/env.js";
1824
import { testing as cliBackendsTesting } from "../cli-backends.js";
1925
import { hashCliSessionText } from "../cli-session.js";
@@ -276,6 +282,7 @@ describe("shouldSkipLocalCliCredentialEpoch", () => {
276282
ensureSandboxWorkspaceForSessionMock.mockReset();
277283
resetContextWindowCacheForTest();
278284
clearMemoryPluginState();
285+
setActivePluginRegistry(createTestRegistry());
279286
vi.unstubAllEnvs();
280287
sessionFileEnvSnapshot?.restore();
281288
sessionFileEnvSnapshot = undefined;
@@ -1012,6 +1019,45 @@ describe("shouldSkipLocalCliCredentialEpoch", () => {
10121019
}
10131020
});
10141021

1022+
it("passes Telegram rich text capabilities into CLI system prompts", async () => {
1023+
const { dir, sessionFile } = createSessionFile();
1024+
setActivePluginRegistry(
1025+
createTestRegistry([
1026+
{
1027+
pluginId: "telegram",
1028+
source: "test",
1029+
plugin: {
1030+
...createChannelTestPluginBase({ id: "telegram", label: "Telegram" }),
1031+
agentPrompt: {
1032+
messageToolCapabilities: () => ["richText"],
1033+
},
1034+
} satisfies ChannelPlugin,
1035+
},
1036+
]),
1037+
);
1038+
1039+
try {
1040+
const context = await prepareCliRunContext({
1041+
sessionId: "session-test",
1042+
sessionFile,
1043+
workspaceDir: dir,
1044+
prompt: "latest ask",
1045+
provider: "test-cli",
1046+
model: "test-model",
1047+
timeoutMs: 1_000,
1048+
runId: "run-test-telegram-rich-text",
1049+
messageChannel: "telegram",
1050+
config: createCliBackendConfig(),
1051+
});
1052+
1053+
expect(context.systemPrompt).toContain("channel=telegram");
1054+
expect(context.systemPrompt).toContain("Telegram rich text is available");
1055+
expect(context.systemPrompt).toContain("This is not legacy MarkdownV2/parse_mode");
1056+
} finally {
1057+
fs.rmSync(dir, { recursive: true, force: true });
1058+
}
1059+
});
1060+
10151061
it("ignores volatile prompt text when static prompt text matches", async () => {
10161062
const { dir, sessionFile } = createSessionFile();
10171063
try {

src/agents/cli-runner/prepare.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { annotateInterSessionPromptText } from "../../sessions/input-provenance.
2828
import { resolveSkillsPromptForRun } from "../../skills/loading/workspace.js";
2929
import { resolveEmbeddedRunSkillEntries } from "../../skills/runtime/embedded-run-entries.js";
3030
import { resolveUserPath } from "../../utils.js";
31+
import { normalizeMessageChannel } from "../../utils/message-channel.js";
3132
import { resolveAgentDir, resolveSessionAgentIds } from "../agent-scope.js";
3233
import { externalCliDiscoveryForProviderAuth } from "../auth-profiles/external-cli-discovery.js";
3334
import { loadAuthProfileStoreForRuntime } from "../auth-profiles/store.js";
@@ -70,6 +71,7 @@ import {
7071
} from "../embedded-agent-runner/sandbox-skills.js";
7172
import { resolveHeartbeatPromptForSystemPrompt } from "../heartbeat-system-prompt.js";
7273
import { applyPluginTextReplacements } from "../plugin-text-transforms.js";
74+
import { collectRuntimeChannelCapabilities } from "../runtime-capabilities.js";
7375
import { ensureSandboxWorkspaceForSession } from "../sandbox.js";
7476
import { ensureSystemPromptCacheBoundary } from "../system-prompt-cache-boundary.js";
7577
import { buildSystemPromptReport } from "../system-prompt-report.js";
@@ -535,6 +537,12 @@ export async function prepareCliRunContext(
535537
agentId: sessionAgentId,
536538
sessionKey: params.sessionKey?.trim() || params.sessionId,
537539
});
540+
const runtimeChannel = normalizeMessageChannel(params.messageChannel ?? params.messageProvider);
541+
const runtimeCapabilities = collectRuntimeChannelCapabilities({
542+
cfg: params.config,
543+
channel: runtimeChannel,
544+
accountId: params.agentAccountId,
545+
});
538546
const builtSystemPrompt = buildCliAgentSystemPrompt({
539547
workspaceDir,
540548
cwd,
@@ -543,6 +551,9 @@ export async function prepareCliRunContext(
543551
extraSystemPrompt,
544552
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
545553
silentReplyPromptMode: params.silentReplyPromptMode,
554+
runtimeChannel,
555+
runtimeChatType: params.sessionEntry?.chatType,
556+
runtimeCapabilities,
546557
ownerNumbers: params.ownerNumbers,
547558
heartbeatPrompt,
548559
docsPath: openClawReferences.docsPath ?? undefined,

0 commit comments

Comments
 (0)