fix: prevent duplicate agent event emission

This commit is contained in:
Peter Steinberger
2026-01-20 09:24:07 +00:00
parent 9dbc1435a6
commit 94af5a72fc
7 changed files with 182 additions and 30 deletions

View File

@@ -18,6 +18,7 @@ import { loadModelCatalog } from "../agents/model-catalog.js";
import { runEmbeddedPiAgent } from "../agents/pi-embedded.js";
import type { ClawdbotConfig } from "../config/config.js";
import * as configModule from "../config/config.js";
import { emitAgentEvent, onAgentEvent } from "../infra/agent-events.js";
import type { RuntimeEnv } from "../runtime.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
import { createPluginRuntime } from "../plugins/runtime/index.js";
@@ -139,6 +140,43 @@ describe("agentCommand", () => {
});
});
it("does not duplicate agent events from embedded runs", async () => {
await withTempHome(async (home) => {
const store = path.join(home, "sessions.json");
mockConfig(home, store);
const assistantEvents: Array<{ runId: string; text?: string }> = [];
const stop = onAgentEvent((evt) => {
if (evt.stream !== "assistant") return;
assistantEvents.push({
runId: evt.runId,
text: typeof evt.data?.text === "string" ? (evt.data.text as string) : undefined,
});
});
vi.mocked(runEmbeddedPiAgent).mockImplementationOnce(async (params) => {
const runId = (params as { runId?: string } | undefined)?.runId ?? "run";
const data = { text: "hello", delta: "hello" };
(
params as {
onAgentEvent?: (evt: { stream: string; data: Record<string, unknown> }) => void;
}
).onAgentEvent?.({ stream: "assistant", data });
emitAgentEvent({ runId, stream: "assistant", data });
return {
payloads: [{ text: "hello" }],
meta: { agentMeta: { provider: "p", model: "m" } },
} as never;
});
await agentCommand({ message: "hi", to: "+1555" }, runtime);
stop();
const matching = assistantEvents.filter((evt) => evt.text === "hello");
expect(matching).toHaveLength(1);
});
});
it("uses provider/model from agents.defaults.model.primary", async () => {
await withTempHome(async (home) => {
const store = path.join(home, "sessions.json");

View File

@@ -434,6 +434,7 @@ export async function agentCommand(
streamParams: opts.streamParams,
agentDir,
onAgentEvent: (evt) => {
// Track lifecycle end for fallback emission below.
if (
evt.stream === "lifecycle" &&
typeof evt.data?.phase === "string" &&
@@ -441,11 +442,6 @@ export async function agentCommand(
) {
lifecycleEnded = true;
}
emitAgentEvent({
runId,
stream: evt.stream,
data: evt.data,
});
},
});
},