Skip to content

Commit f299bb8

Browse files
authored
test(agents): stabilize announce cleanup assertions (openclaw#61088)
* test(plugin-sdk): use telegram public config seam * test(agents): stabilize announce cleanup assertions
1 parent 04b64e4 commit f299bb8

5 files changed

Lines changed: 95 additions & 57 deletions

File tree

extensions/telegram/channel-config-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export {
2+
TELEGRAM_COMMAND_NAME_PATTERN,
23
normalizeTelegramCommandDescription,
34
normalizeTelegramCommandName,
45
resolveTelegramCustomCommands,

src/agents/pi-tools-agent-config.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ describe("Agent-specific tool filtering", () => {
727727
command: "echo done",
728728
host: "sandbox",
729729
}),
730-
).rejects.toThrow("exec host not allowed");
730+
).rejects.toThrow(/requires a sandbox runtime/);
731731
});
732732

733733
it("should apply agent-specific exec host defaults over global defaults", async () => {
@@ -777,7 +777,7 @@ describe("Agent-specific tool filtering", () => {
777777
host: "sandbox",
778778
yieldMs: 1000,
779779
}),
780-
).rejects.toThrow("exec host not allowed");
780+
).rejects.toThrow(/requires a sandbox runtime/);
781781
});
782782

783783
it("applies explicit agentId exec defaults when sessionKey is opaque", async () => {

src/agents/subagent-announce.test.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ vi.mock("./subagent-announce-delivery.js", () => ({
103103
params: {
104104
sessionKey: params.targetRequesterSessionKey,
105105
message: params.triggerMessage,
106-
deliver: false,
106+
deliver:
107+
!params.requesterIsSubagent &&
108+
params.requesterOrigin?.channel !== "webchat" &&
109+
Boolean(params.requesterOrigin?.channel && params.requesterOrigin?.to),
107110
bestEffortDeliver: params.bestEffortDeliver,
108111
...(params.requesterIsSubagent
109112
? {}
@@ -127,8 +130,27 @@ vi.mock("./subagent-announce-delivery.js", () => ({
127130
const store = loadSessionStoreMock("/tmp/sessions.json") as Record<string, unknown>;
128131
return store?.[sessionKey] ?? { sessionId: sessionKey };
129132
},
130-
resolveAnnounceOrigin: (entry: { origin?: unknown } | undefined, requesterOrigin?: unknown) =>
131-
requesterOrigin ?? entry?.origin,
133+
resolveAnnounceOrigin: (
134+
entry:
135+
| {
136+
lastChannel?: string;
137+
lastTo?: string;
138+
lastAccountId?: string;
139+
lastThreadId?: string;
140+
origin?: { provider?: string; channel?: string; accountId?: string };
141+
}
142+
| undefined,
143+
requesterOrigin?: { channel?: string; to?: string; accountId?: string; threadId?: string },
144+
) => ({
145+
channel:
146+
requesterOrigin?.channel ??
147+
entry?.lastChannel ??
148+
entry?.origin?.provider ??
149+
entry?.origin?.channel,
150+
to: requesterOrigin?.to ?? entry?.lastTo,
151+
accountId: requesterOrigin?.accountId ?? entry?.lastAccountId ?? entry?.origin?.accountId,
152+
threadId: requesterOrigin?.threadId ?? entry?.lastThreadId,
153+
}),
132154
resolveSubagentCompletionOrigin: async (params: { requesterOrigin?: unknown }) =>
133155
params.requesterOrigin,
134156
resolveSubagentAnnounceTimeoutMs: () => 10_000,

src/agents/subagent-registry.steer-restart.test.ts

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,12 @@ describe("subagent registry steer restarts", () => {
263263

264264
emitLifecycleEnd("run-new");
265265

266-
await flushAnnounce();
267-
expect(announceSpy).toHaveBeenCalledTimes(1);
268-
expect(runSubagentEndedHookMock).toHaveBeenCalledTimes(1);
266+
await vi.waitFor(() => {
267+
expect(announceSpy).toHaveBeenCalledTimes(1);
268+
});
269+
await vi.waitFor(() => {
270+
expect(runSubagentEndedHookMock).toHaveBeenCalledTimes(1);
271+
});
269272
expect(runSubagentEndedHookMock).toHaveBeenCalledWith(
270273
expect.objectContaining({
271274
runId: "run-new",
@@ -338,63 +341,75 @@ describe("subagent registry steer restarts", () => {
338341
});
339342
});
340343

341-
it("clears announce retry state when replacing after steer restart", () => {
342-
registerRun({
343-
runId: "run-retry-reset-old",
344-
childSessionKey: "agent:main:subagent:retry-reset",
345-
task: "retry reset",
346-
});
344+
it("clears announce retry state when replacing after steer restart", async () => {
345+
await withPendingAgentWait(async () => {
346+
registerRun({
347+
runId: "run-retry-reset-old",
348+
childSessionKey: "agent:main:subagent:retry-reset",
349+
task: "retry reset",
350+
});
347351

348-
const previous = listMainRuns()[0];
349-
expect(previous?.runId).toBe("run-retry-reset-old");
350-
if (previous) {
351-
previous.announceRetryCount = 2;
352-
previous.lastAnnounceRetryAt = Date.now();
353-
}
352+
const previous = listMainRuns()[0];
353+
expect(previous?.runId).toBe("run-retry-reset-old");
354+
if (previous) {
355+
previous.announceRetryCount = 2;
356+
previous.lastAnnounceRetryAt = Date.now();
357+
}
354358

355-
const run = replaceRunAfterSteer({
356-
previousRunId: "run-retry-reset-old",
357-
nextRunId: "run-retry-reset-new",
358-
fallback: previous,
359+
const run = replaceRunAfterSteer({
360+
previousRunId: "run-retry-reset-old",
361+
nextRunId: "run-retry-reset-new",
362+
fallback: previous,
363+
});
364+
expect(run.announceRetryCount).toBeUndefined();
365+
expect(run.lastAnnounceRetryAt).toBeUndefined();
359366
});
360-
expect(run.announceRetryCount).toBeUndefined();
361-
expect(run.lastAnnounceRetryAt).toBeUndefined();
362367
});
363368

364369
it("clears terminal lifecycle state when replacing after steer restart", async () => {
365-
registerRun({
366-
runId: "run-terminal-state-old",
367-
childSessionKey: "agent:main:subagent:terminal-state",
368-
task: "terminal state",
369-
});
370+
await withPendingAgentWait(async () => {
371+
registerRun({
372+
runId: "run-terminal-state-old",
373+
childSessionKey: "agent:main:subagent:terminal-state",
374+
task: "terminal state",
375+
});
370376

371-
const previous = listMainRuns()[0];
372-
expect(previous?.runId).toBe("run-terminal-state-old");
373-
if (previous) {
374-
previous.endedHookEmittedAt = Date.now();
375-
previous.endedReason = "subagent-complete";
376-
previous.endedAt = Date.now();
377-
previous.outcome = { status: "ok" };
378-
}
377+
const previous = listMainRuns()[0];
378+
expect(previous?.runId).toBe("run-terminal-state-old");
379+
if (previous) {
380+
previous.endedHookEmittedAt = Date.now();
381+
previous.endedReason = "subagent-complete";
382+
previous.endedAt = Date.now();
383+
previous.outcome = { status: "ok" };
384+
}
379385

380-
const run = replaceRunAfterSteer({
381-
previousRunId: "run-terminal-state-old",
382-
nextRunId: "run-terminal-state-new",
383-
fallback: previous,
386+
const run = replaceRunAfterSteer({
387+
previousRunId: "run-terminal-state-old",
388+
nextRunId: "run-terminal-state-new",
389+
fallback: previous,
390+
});
391+
expect(run.endedHookEmittedAt).toBeUndefined();
392+
expect(run.endedReason).toBeUndefined();
393+
394+
emitLifecycleEnd("run-terminal-state-new");
395+
396+
await vi.waitFor(() => {
397+
expect(runSubagentEndedHookMock).toHaveBeenCalledWith(
398+
expect.objectContaining({
399+
runId: "run-terminal-state-new",
400+
}),
401+
expect.objectContaining({
402+
runId: "run-terminal-state-new",
403+
}),
404+
);
405+
});
406+
expect(emitSessionLifecycleEventMock).toHaveBeenCalledWith(
407+
expect.objectContaining({
408+
sessionKey: "agent:main:subagent:terminal-state",
409+
reason: "subagent-status",
410+
}),
411+
);
384412
});
385-
expect(run.endedHookEmittedAt).toBeUndefined();
386-
expect(run.endedReason).toBeUndefined();
387-
388-
emitLifecycleEnd("run-terminal-state-new");
389-
390-
await flushAnnounce();
391-
expect(runSubagentEndedHookMock).not.toHaveBeenCalled();
392-
expect(emitSessionLifecycleEventMock).toHaveBeenCalledWith(
393-
expect.objectContaining({
394-
sessionKey: "agent:main:subagent:terminal-state",
395-
reason: "subagent-status",
396-
}),
397-
);
398413
});
399414

400415
it("clears frozen completion fields when replacing after steer restart", () => {

src/plugin-sdk/telegram-command-config.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it, vi } from "vitest";
2-
import { TELEGRAM_COMMAND_NAME_PATTERN as bundledTelegramCommandNamePattern } from "../../extensions/telegram/src/command-config.ts";
2+
import { TELEGRAM_COMMAND_NAME_PATTERN as bundledTelegramCommandNamePattern } from "../../extensions/telegram/channel-config-api.ts";
33

44
type BundledChannelContractSurfaceParams = Parameters<
55
(typeof import("../channels/plugins/contract-surfaces.js"))["getBundledChannelContractSurfaceModule"]

0 commit comments

Comments
 (0)