mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
test(agents): slim embedded runner hotspot coverage
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
cleanupTempPaths,
|
||||
createContextEngineAttemptRunner,
|
||||
createContextEngineBootstrapAndAssemble,
|
||||
resetEmbeddedAttemptHarness,
|
||||
} from "./attempt.spawn-workspace.test-support.js";
|
||||
|
||||
describe("runEmbeddedAttempt empty prompt guard", () => {
|
||||
const tempPaths: string[] = [];
|
||||
|
||||
beforeEach(() => {
|
||||
resetEmbeddedAttemptHarness();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await cleanupTempPaths(tempPaths);
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("skips provider submission when prompt, history, and images are empty", async () => {
|
||||
const sessionPrompt = vi.fn(async () => {});
|
||||
const { assemble } = createContextEngineBootstrapAndAssemble();
|
||||
|
||||
const result = await createContextEngineAttemptRunner({
|
||||
contextEngine: { assemble },
|
||||
sessionKey: "agent:main:guildchat:dm:empty-prompt",
|
||||
tempPaths,
|
||||
sessionMessages: [],
|
||||
sessionPrompt,
|
||||
attemptOverrides: {
|
||||
prompt: " ",
|
||||
},
|
||||
});
|
||||
|
||||
expect(sessionPrompt).not.toHaveBeenCalled();
|
||||
expect(result.promptError).toBeNull();
|
||||
expect(result.finalPromptText).toBeUndefined();
|
||||
expect(result.messagesSnapshot).toEqual([]);
|
||||
expect(result.assistantTexts).toEqual([]);
|
||||
});
|
||||
|
||||
it("still submits a blank prompt when replay history has content", async () => {
|
||||
const sessionPrompt = vi.fn(async () => {});
|
||||
const { assemble } = createContextEngineBootstrapAndAssemble();
|
||||
const sessionMessages = [
|
||||
{ role: "user", content: "previous turn", timestamp: 1 },
|
||||
] as AgentMessage[];
|
||||
|
||||
await createContextEngineAttemptRunner({
|
||||
contextEngine: { assemble },
|
||||
sessionKey: "agent:main:guildchat:dm:empty-prompt-with-history",
|
||||
tempPaths,
|
||||
sessionMessages,
|
||||
sessionPrompt,
|
||||
attemptOverrides: {
|
||||
prompt: " ",
|
||||
},
|
||||
});
|
||||
|
||||
expect(sessionPrompt).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,10 @@ const videoGenerationTaskStatusMocks = vi.hoisted(() => ({
|
||||
vi.mock("../../music-generation-task-status.js", () => musicGenerationTaskStatusMocks);
|
||||
vi.mock("../../video-generation-task-status.js", () => videoGenerationTaskStatusMocks);
|
||||
|
||||
import { resolveAttemptPrependSystemContext } from "./attempt.prompt-helpers.js";
|
||||
import {
|
||||
hasPromptSubmissionContent,
|
||||
resolveAttemptPrependSystemContext,
|
||||
} from "./attempt.prompt-helpers.js";
|
||||
|
||||
describe("resolveAttemptPrependSystemContext", () => {
|
||||
it("prepends active video task guidance ahead of hook system context", () => {
|
||||
@@ -62,3 +65,42 @@ describe("resolveAttemptPrependSystemContext", () => {
|
||||
expect(result).toBe("Hook system context");
|
||||
});
|
||||
});
|
||||
|
||||
describe("hasPromptSubmissionContent", () => {
|
||||
it("rejects empty prompt submissions without history or images", () => {
|
||||
expect(
|
||||
hasPromptSubmissionContent({
|
||||
prompt: " ",
|
||||
messages: [],
|
||||
imageCount: 0,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("allows blank prompt submissions when replay history has content", () => {
|
||||
expect(
|
||||
hasPromptSubmissionContent({
|
||||
prompt: " ",
|
||||
messages: [{ role: "user", content: "previous turn", timestamp: 1 }],
|
||||
imageCount: 0,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("allows text or image prompt submissions", () => {
|
||||
expect(
|
||||
hasPromptSubmissionContent({
|
||||
prompt: "hello",
|
||||
messages: [],
|
||||
imageCount: 0,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
hasPromptSubmissionContent({
|
||||
prompt: " ",
|
||||
messages: [],
|
||||
imageCount: 1,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -122,6 +122,14 @@ export function shouldWarnOnOrphanedUserRepair(
|
||||
return trigger === "user" || trigger === "manual";
|
||||
}
|
||||
|
||||
export function hasPromptSubmissionContent(params: {
|
||||
prompt: string;
|
||||
messages: readonly unknown[];
|
||||
imageCount: number;
|
||||
}): boolean {
|
||||
return params.prompt.trim().length > 0 || params.messages.length > 0 || params.imageCount > 0;
|
||||
}
|
||||
|
||||
const QUEUED_USER_MESSAGE_MARKER =
|
||||
"[Queued user message that arrived while the previous turn was still active]";
|
||||
const MAX_STRUCTURED_MEDIA_REF_CHARS = 300;
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
import {
|
||||
cleanupTempPaths,
|
||||
createContextEngineBootstrapAndAssemble,
|
||||
createContextEngineAttemptRunner,
|
||||
expectCalledWithSessionKey,
|
||||
getHoisted,
|
||||
resetEmbeddedAttemptHarness,
|
||||
@@ -277,81 +276,6 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
expect(params.sessionKey).toBe(sessionKey);
|
||||
});
|
||||
|
||||
it("prechecks unwindowed context before submitting a windowed context-engine prompt", async () => {
|
||||
const sessionPrompt = vi.fn(async () => {});
|
||||
const fullHistory = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "large historical context ".repeat(600) }],
|
||||
timestamp: 1,
|
||||
},
|
||||
] as AgentMessage[];
|
||||
const windowedMessages = [
|
||||
{ role: "assistant", content: [{ type: "text", text: "small window" }], timestamp: 2 },
|
||||
] as AgentMessage[];
|
||||
const assemble = vi.fn(async () => ({
|
||||
messages: windowedMessages,
|
||||
estimatedTokens: 3,
|
||||
}));
|
||||
|
||||
const result = await createContextEngineAttemptRunner({
|
||||
contextEngine: { assemble },
|
||||
sessionKey,
|
||||
tempPaths,
|
||||
sessionMessages: fullHistory,
|
||||
sessionPrompt,
|
||||
attemptOverrides: {
|
||||
contextTokenBudget: 512,
|
||||
},
|
||||
});
|
||||
|
||||
expect(assemble).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
messages: fullHistory,
|
||||
}),
|
||||
);
|
||||
expect(sessionPrompt).not.toHaveBeenCalled();
|
||||
expect(result.promptErrorSource).toBe("precheck");
|
||||
expect(result.preflightRecovery).toEqual({ route: "compact_only" });
|
||||
});
|
||||
|
||||
it("keeps preflight overflow checks active for engines that own compaction", async () => {
|
||||
const sessionPrompt = vi.fn(async () => {});
|
||||
const fullHistory = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "engine-owned large historical context ".repeat(600) }],
|
||||
timestamp: 1,
|
||||
},
|
||||
] as AgentMessage[];
|
||||
const assemble = vi.fn(async () => ({
|
||||
messages: [
|
||||
{ role: "assistant", content: [{ type: "text", text: "small window" }], timestamp: 2 },
|
||||
] as AgentMessage[],
|
||||
estimatedTokens: 3,
|
||||
}));
|
||||
|
||||
const result = await createContextEngineAttemptRunner({
|
||||
contextEngine: {
|
||||
assemble,
|
||||
info: {
|
||||
ownsCompaction: true,
|
||||
},
|
||||
},
|
||||
sessionKey,
|
||||
tempPaths,
|
||||
sessionMessages: fullHistory,
|
||||
sessionPrompt,
|
||||
attemptOverrides: {
|
||||
contextTokenBudget: 512,
|
||||
},
|
||||
});
|
||||
|
||||
expect(sessionPrompt).not.toHaveBeenCalled();
|
||||
expect(result.promptErrorSource).toBe("precheck");
|
||||
expect(result.preflightRecovery).toEqual({ route: "compact_only" });
|
||||
});
|
||||
|
||||
it("skips maintenance when afterTurn fails", async () => {
|
||||
const { bootstrap, assemble } = createContextEngineBootstrapAndAssemble();
|
||||
const afterTurn = vi.fn(async () => {
|
||||
|
||||
@@ -252,6 +252,7 @@ import {
|
||||
resolveAttemptPrependSystemContext,
|
||||
resolvePromptBuildHookResult,
|
||||
resolvePromptModeForSession,
|
||||
hasPromptSubmissionContent,
|
||||
shouldWarnOnOrphanedUserRepair,
|
||||
shouldInjectHeartbeatPrompt,
|
||||
} from "./attempt.prompt-helpers.js";
|
||||
@@ -453,14 +454,6 @@ function summarizeSessionContext(messages: AgentMessage[]): {
|
||||
};
|
||||
}
|
||||
|
||||
function hasPromptSubmissionContent(params: {
|
||||
prompt: string;
|
||||
messages: readonly AgentMessage[];
|
||||
imageCount: number;
|
||||
}): boolean {
|
||||
return params.prompt.trim().length > 0 || params.messages.length > 0 || params.imageCount > 0;
|
||||
}
|
||||
|
||||
export function applyEmbeddedAttemptToolsAllow<T extends { name: string }>(
|
||||
tools: T[],
|
||||
toolsAllow?: string[],
|
||||
|
||||
Reference in New Issue
Block a user