Files
openclaw/src/agents/subagent-announce.format.test.ts
2026-01-15 23:44:31 +00:00

90 lines
3.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const agentSpy = vi.fn(async () => ({ runId: "run-main", status: "ok" }));
vi.mock("../gateway/call.js", () => ({
callGateway: vi.fn(async (req: unknown) => {
const typed = req as { method?: string; params?: { message?: string; sessionKey?: string } };
if (typed.method === "agent") {
return await agentSpy(typed);
}
if (typed.method === "agent.wait") {
return { status: "error", startedAt: 10, endedAt: 20, error: "boom" };
}
if (typed.method === "sessions.patch") return {};
if (typed.method === "sessions.delete") return {};
return {};
}),
}));
vi.mock("./tools/agent-step.js", () => ({
readLatestAssistantReply: vi.fn(async () => "raw subagent reply"),
}));
vi.mock("../config/sessions.js", () => ({
loadSessionStore: vi.fn(() => ({})),
resolveAgentIdFromSessionKey: () => "main",
resolveStorePath: () => "/tmp/sessions.json",
}));
vi.mock("../config/config.js", () => ({
loadConfig: () => ({
session: { mainKey: "agent:main:main" },
}),
}));
describe("subagent announce formatting", () => {
beforeEach(() => {
agentSpy.mockClear();
});
it("sends instructional message to main agent with status and findings", async () => {
const { runSubagentAnnounceFlow } = await import("./subagent-announce.js");
await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:test",
childRunId: "run-123",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
task: "do thing",
timeoutMs: 1000,
cleanup: "keep",
waitForCompletion: true,
startedAt: 10,
endedAt: 20,
});
expect(agentSpy).toHaveBeenCalled();
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string; sessionKey?: string } };
const msg = call?.params?.message as string;
expect(call?.params?.sessionKey).toBe("agent:main:main");
expect(msg).toContain("background task");
expect(msg).toContain("failed");
expect(msg).toContain("boom");
expect(msg).toContain("Findings:");
expect(msg).toContain("raw subagent reply");
expect(msg).toContain("Stats:");
});
it("includes success status when outcome is ok", async () => {
const { runSubagentAnnounceFlow } = await import("./subagent-announce.js");
// Use waitForCompletion: false so it uses the provided outcome instead of calling agent.wait
await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:test",
childRunId: "run-456",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
task: "do thing",
timeoutMs: 1000,
cleanup: "keep",
waitForCompletion: false,
startedAt: 10,
endedAt: 20,
outcome: { status: "ok" },
});
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
const msg = call?.params?.message as string;
expect(msg).toContain("completed successfully");
});
});