fix: cover CLI session prompt hash reuse (#69236) (thanks @stainlu)

This commit is contained in:
Ayaan Zaidi
2026-04-25 15:51:10 +05:30
parent 7711df0669
commit bbd6dfbe92

View File

@@ -6,6 +6,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
import { __testing as cliBackendsTesting } from "../cli-backends.js";
import { hashCliSessionText } from "../cli-session.js";
import { buildActiveMusicGenerationTaskPromptContextForSession } from "../music-generation-task-status.js";
import { buildActiveVideoGenerationTaskPromptContextForSession } from "../video-generation-task-status.js";
import {
@@ -52,11 +53,15 @@ const mockBuildActiveMusicGenerationTaskPromptContextForSession = vi.mocked(
buildActiveMusicGenerationTaskPromptContextForSession,
);
function createCliBackendConfig(params: { systemPromptOverride?: string } = {}): OpenClawConfig {
function createCliBackendConfig(
params: { systemPromptOverride?: string | null } = {},
): OpenClawConfig {
return {
agents: {
defaults: {
systemPromptOverride: params.systemPromptOverride ?? "test system prompt",
...(params.systemPromptOverride !== null
? { systemPromptOverride: params.systemPromptOverride ?? "test system prompt" }
: {}),
cliBackends: {
"test-cli": {
command: "test-cli",
@@ -308,7 +313,7 @@ describe("shouldSkipLocalCliCredentialEpoch", () => {
model: "test-model",
timeoutMs: 1_000,
runId: "run-test-legacy-merge",
config: createCliBackendConfig(),
config: createCliBackendConfig({ systemPromptOverride: null }),
});
expect(context.params.prompt).toBe("prompt prepend\n\nlegacy prepend\n\nlatest ask");
@@ -355,6 +360,63 @@ describe("shouldSkipLocalCliCredentialEpoch", () => {
}
});
it("uses explicit static prompt text for CLI session reuse hashing", async () => {
const { dir, sessionFile } = createSessionFile();
try {
const context = await prepareCliRunContext({
sessionId: "session-test",
sessionFile,
workspaceDir: dir,
prompt: "latest ask",
provider: "test-cli",
model: "test-model",
timeoutMs: 1_000,
runId: "run-test-static-prompt",
extraSystemPrompt: "## Inbound Context\nchannel=telegram",
extraSystemPromptStatic: "",
cliSessionBinding: {
sessionId: "cli-session",
},
config: createCliBackendConfig({ systemPromptOverride: null }),
});
expect(context.systemPrompt).toContain("## Inbound Context\nchannel=telegram");
expect(context.extraSystemPromptHash).toBeUndefined();
expect(context.reusableCliSession).toEqual({ sessionId: "cli-session" });
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
it("ignores volatile prompt text when static prompt text matches", async () => {
const { dir, sessionFile } = createSessionFile();
try {
const staticPrompt = "## Direct Context\nYou are in a Telegram direct conversation.";
const context = await prepareCliRunContext({
sessionId: "session-test",
sessionFile,
workspaceDir: dir,
prompt: "latest ask",
provider: "test-cli",
model: "test-model",
timeoutMs: 1_000,
runId: "run-test-volatile-prompt",
extraSystemPrompt: `## Inbound Context\nchannel=heartbeat\n\n${staticPrompt}`,
extraSystemPromptStatic: staticPrompt,
cliSessionBinding: {
sessionId: "cli-session",
extraSystemPromptHash: hashCliSessionText(staticPrompt),
},
config: createCliBackendConfig(),
});
expect(context.extraSystemPromptHash).toBe(hashCliSessionText(staticPrompt));
expect(context.reusableCliSession).toEqual({ sessionId: "cli-session" });
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
it("applies direct-run prepend system context helpers on the CLI path", async () => {
const { dir, sessionFile } = createSessionFile();
try {