mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 15:24:58 +00:00
fix: agent-only announce path, BB message IDs, sender identity, SSRF allowlist (#23970)
* fix(agents): defer announces until descendant cleanup settles * fix(bluebubbles): harden message metadata extraction * feat(contributors): rank by composite score (commits, PRs, LOC, tenure) * refactor(control-ui): move method guard after path checks to improve request handling * fix subagent completion announce when only current run is pending * fix(subagents): keep orchestrator runs active until descendants finish * fix: prepare PR feedback follow-ups (#23970) (thanks @tyler6204)
This commit is contained in:
@@ -34,6 +34,8 @@ const embeddedRunMock = {
|
||||
const subagentRegistryMock = {
|
||||
isSubagentSessionRunActive: vi.fn(() => true),
|
||||
countActiveDescendantRuns: vi.fn((_sessionKey: string) => 0),
|
||||
countPendingDescendantRuns: vi.fn((_sessionKey: string) => 0),
|
||||
countPendingDescendantRunsExcludingRun: vi.fn((_sessionKey: string, _runId: string) => 0),
|
||||
resolveRequesterForChildSession: vi.fn((_sessionKey: string): RequesterResolution => null),
|
||||
};
|
||||
const subagentDeliveryTargetHookMock = vi.fn(
|
||||
@@ -172,6 +174,16 @@ describe("subagent announce formatting", () => {
|
||||
embeddedRunMock.waitForEmbeddedPiRunEnd.mockClear().mockResolvedValue(true);
|
||||
subagentRegistryMock.isSubagentSessionRunActive.mockClear().mockReturnValue(true);
|
||||
subagentRegistryMock.countActiveDescendantRuns.mockClear().mockReturnValue(0);
|
||||
subagentRegistryMock.countPendingDescendantRuns
|
||||
.mockClear()
|
||||
.mockImplementation((sessionKey: string) =>
|
||||
subagentRegistryMock.countActiveDescendantRuns(sessionKey),
|
||||
);
|
||||
subagentRegistryMock.countPendingDescendantRunsExcludingRun
|
||||
.mockClear()
|
||||
.mockImplementation((sessionKey: string, _runId: string) =>
|
||||
subagentRegistryMock.countPendingDescendantRuns(sessionKey),
|
||||
);
|
||||
subagentRegistryMock.resolveRequesterForChildSession.mockClear().mockReturnValue(null);
|
||||
hasSubagentDeliveryTargetHook = false;
|
||||
hookRunnerMock.hasHooks.mockClear();
|
||||
@@ -408,6 +420,45 @@ describe("subagent announce formatting", () => {
|
||||
expect(msg).not.toContain("Convert the result above into your normal assistant voice");
|
||||
});
|
||||
|
||||
it("keeps direct completion send when only the announcing run itself is pending", async () => {
|
||||
sessionStore = {
|
||||
"agent:main:subagent:test": {
|
||||
sessionId: "child-session-self-pending",
|
||||
},
|
||||
"agent:main:main": {
|
||||
sessionId: "requester-session-self-pending",
|
||||
},
|
||||
};
|
||||
chatHistoryMock.mockResolvedValueOnce({
|
||||
messages: [{ role: "assistant", content: [{ type: "text", text: "final answer: done" }] }],
|
||||
});
|
||||
subagentRegistryMock.countPendingDescendantRuns.mockImplementation((sessionKey: string) =>
|
||||
sessionKey === "agent:main:main" ? 1 : 0,
|
||||
);
|
||||
subagentRegistryMock.countPendingDescendantRunsExcludingRun.mockImplementation(
|
||||
(sessionKey: string, runId: string) =>
|
||||
sessionKey === "agent:main:main" && runId === "run-direct-self-pending" ? 0 : 1,
|
||||
);
|
||||
|
||||
const didAnnounce = await runSubagentAnnounceFlow({
|
||||
childSessionKey: "agent:main:subagent:test",
|
||||
childRunId: "run-direct-self-pending",
|
||||
requesterSessionKey: "agent:main:main",
|
||||
requesterDisplayKey: "main",
|
||||
requesterOrigin: { channel: "discord", to: "channel:12345", accountId: "acct-1" },
|
||||
...defaultOutcomeAnnounce,
|
||||
expectsCompletionMessage: true,
|
||||
});
|
||||
|
||||
expect(didAnnounce).toBe(true);
|
||||
expect(subagentRegistryMock.countPendingDescendantRunsExcludingRun).toHaveBeenCalledWith(
|
||||
"agent:main:main",
|
||||
"run-direct-self-pending",
|
||||
);
|
||||
expect(sendSpy).toHaveBeenCalledTimes(1);
|
||||
expect(agentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("suppresses completion delivery when subagent reply is ANNOUNCE_SKIP", async () => {
|
||||
const didAnnounce = await runSubagentAnnounceFlow({
|
||||
childSessionKey: "agent:main:subagent:test",
|
||||
|
||||
Reference in New Issue
Block a user