feat: refine subagents + add chat.inject
Co-authored-by: Tyler Yust <tyler6204@users.noreply.github.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const sendSpy = vi.fn(async () => ({}));
|
||||
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 } };
|
||||
if (typed.method === "send") {
|
||||
return await sendSpy(typed);
|
||||
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" };
|
||||
@@ -18,24 +18,11 @@ vi.mock("../gateway/call.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("./tools/agent-step.js", () => ({
|
||||
runAgentStep: vi.fn(async () => "did some stuff"),
|
||||
readLatestAssistantReply: vi.fn(async () => "raw subagent reply"),
|
||||
}));
|
||||
|
||||
vi.mock("./tools/sessions-announce-target.js", () => ({
|
||||
resolveAnnounceTarget: vi.fn(async () => ({
|
||||
provider: "telegram",
|
||||
to: "+15550001111",
|
||||
accountId: "default",
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("./tools/sessions-send-helpers.js", () => ({
|
||||
isAnnounceSkip: () => false,
|
||||
}));
|
||||
|
||||
vi.mock("../config/sessions.js", () => ({
|
||||
loadSessionStore: vi.fn(async () => ({ entries: {} })),
|
||||
loadSessionStore: vi.fn(() => ({})),
|
||||
resolveAgentIdFromSessionKey: () => "main",
|
||||
resolveStorePath: () => "/tmp/sessions.json",
|
||||
}));
|
||||
@@ -48,10 +35,10 @@ vi.mock("../config/config.js", () => ({
|
||||
|
||||
describe("subagent announce formatting", () => {
|
||||
beforeEach(() => {
|
||||
sendSpy.mockClear();
|
||||
agentSpy.mockClear();
|
||||
});
|
||||
|
||||
it("wraps unstructured announce into Status/Result/Notes", async () => {
|
||||
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",
|
||||
@@ -66,22 +53,21 @@ describe("subagent announce formatting", () => {
|
||||
endedAt: 20,
|
||||
});
|
||||
|
||||
expect(sendSpy).toHaveBeenCalled();
|
||||
const msg = sendSpy.mock.calls[0]?.[0]?.params?.message as string;
|
||||
expect(msg).toContain("Status:");
|
||||
expect(msg).toContain("Status: error");
|
||||
expect(msg).toContain("Result:");
|
||||
expect(msg).toContain("Notes:");
|
||||
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("keeps runtime status even when announce reply is structured", async () => {
|
||||
const agentStep = await import("./tools/agent-step.js");
|
||||
vi.mocked(agentStep.runAgentStep).mockResolvedValueOnce(
|
||||
"- **Status:** success\n\n- **Result:** did some stuff\n\n- **Notes:** all good",
|
||||
);
|
||||
|
||||
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",
|
||||
@@ -90,14 +76,14 @@ describe("subagent announce formatting", () => {
|
||||
task: "do thing",
|
||||
timeoutMs: 1000,
|
||||
cleanup: "keep",
|
||||
waitForCompletion: true,
|
||||
waitForCompletion: false,
|
||||
startedAt: 10,
|
||||
endedAt: 20,
|
||||
outcome: { status: "ok" },
|
||||
});
|
||||
|
||||
const msg = sendSpy.mock.calls[0]?.[0]?.params?.message as string;
|
||||
expect(msg).toContain("Status: error");
|
||||
expect(msg).toContain("Result:");
|
||||
expect(msg).toContain("Notes:");
|
||||
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
|
||||
const msg = call?.params?.message as string;
|
||||
expect(msg).toContain("completed successfully");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user