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:
Tyler Yust
2026-03-01 22:52:11 -08:00
committed by GitHub
parent cfba64c9db
commit f918b336d1
22 changed files with 814 additions and 155 deletions

View File

@@ -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",