fix: dedupe verbose subagent status counts

This commit is contained in:
Tak Hoffman 2026-03-24 16:18:03 -05:00
parent 51e59983a1
commit a4ccd75ff3
No known key found for this signature in database
2 changed files with 65 additions and 2 deletions

View File

@ -70,4 +70,60 @@ describe("buildStatusReply subagent summary", () => {
expect(reply?.text).toContain("🤖 Subagents: 1 active");
});
it("dedupes stale rows in the verbose subagent status summary", async () => {
const childSessionKey = "agent:main:subagent:status-dedupe-worker";
addSubagentRunForTests({
runId: "run-status-current",
childSessionKey,
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
task: "current status worker",
cleanup: "keep",
createdAt: Date.now() - 60_000,
startedAt: Date.now() - 60_000,
});
addSubagentRunForTests({
runId: "run-status-stale",
childSessionKey,
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
task: "stale status worker",
cleanup: "keep",
createdAt: Date.now() - 120_000,
startedAt: Date.now() - 120_000,
endedAt: Date.now() - 90_000,
outcome: { status: "ok" },
});
const cfg = {
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
session: { mainKey: "main", scope: "per-sender" },
} as OpenClawConfig;
const params = buildCommandTestParams("/status", cfg);
const reply = await buildStatusReply({
cfg,
command: params.command,
sessionEntry: params.sessionEntry,
sessionKey: params.sessionKey,
parentSessionKey: params.sessionKey,
sessionScope: params.sessionScope,
storePath: params.storePath,
provider: "anthropic",
model: "claude-opus-4-5",
contextTokens: 0,
resolvedThinkLevel: params.resolvedThinkLevel,
resolvedFastMode: false,
resolvedVerboseLevel: "on",
resolvedReasoningLevel: params.resolvedReasoningLevel,
resolvedElevatedLevel: params.resolvedElevatedLevel,
resolveDefaultThinkingLevel: params.resolveDefaultThinkingLevel,
isGroup: params.isGroup,
defaultGroupActivation: params.defaultGroupActivation,
});
expect(reply?.text).toContain("🤖 Subagents: 1 active");
expect(reply?.text).not.toContain("· 1 done");
});
});

View File

@ -30,7 +30,7 @@ import type { ElevatedLevel, ReasoningLevel, ThinkLevel, VerboseLevel } from "..
import type { ReplyPayload } from "../types.js";
import type { CommandContext } from "./commands-types.js";
import { getFollowupQueueDepth, resolveQueueSettings } from "./queue.js";
import { resolveSubagentLabel } from "./subagents-utils.js";
import { resolveSubagentLabel, sortSubagentRuns } from "./subagents-utils.js";
// Some usage endpoints only work with CLI/session OAuth tokens, not API keys.
// Skip those probes when the active auth mode cannot satisfy the endpoint.
@ -188,7 +188,14 @@ export async function buildStatusReply(params: {
if (sessionKey) {
const { mainKey, alias } = resolveMainSessionAlias(cfg);
const requesterKey = resolveInternalSessionKey({ key: sessionKey, alias, mainKey });
const runs = listSubagentRunsForRequester(requesterKey);
const seenChildSessionKeys = new Set<string>();
const runs = sortSubagentRuns(listSubagentRunsForRequester(requesterKey)).filter((entry) => {
if (seenChildSessionKeys.has(entry.childSessionKey)) {
return false;
}
seenChildSessionKeys.add(entry.childSessionKey);
return true;
});
const verboseEnabled = resolvedVerboseLevel && resolvedVerboseLevel !== "off";
if (runs.length > 0) {
const active = runs.filter(