mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-27 01:41:40 +00:00
fix: align /agents ids with subagent targets
This commit is contained in:
@@ -75,4 +75,71 @@ describe("handleSubagentsAgentsAction", () => {
|
||||
expect(result.reply?.text).toContain("current worker label");
|
||||
expect(result.reply?.text).not.toContain("stale worker label");
|
||||
});
|
||||
|
||||
it("keeps /agents numbering aligned with target resolution when hidden recent rows exist", () => {
|
||||
const hiddenSessionKey = "agent:main:subagent:hidden-recent";
|
||||
const visibleSessionKey = "agent:main:subagent:visible-bound";
|
||||
listBySessionMock.mockImplementation((sessionKey: string) =>
|
||||
sessionKey === visibleSessionKey
|
||||
? [
|
||||
{
|
||||
bindingId: "binding-visible",
|
||||
targetSessionKey: visibleSessionKey,
|
||||
targetKind: "subagent",
|
||||
conversation: {
|
||||
channel: "discord",
|
||||
accountId: "default",
|
||||
conversationId: "thread-visible",
|
||||
},
|
||||
status: "active",
|
||||
boundAt: Date.now() - 20_000,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
);
|
||||
|
||||
const result = handleSubagentsAgentsAction({
|
||||
params: {
|
||||
ctx: {
|
||||
Provider: "discord",
|
||||
Surface: "discord",
|
||||
},
|
||||
command: {
|
||||
channel: "discord",
|
||||
},
|
||||
},
|
||||
requesterKey: "agent:main:main",
|
||||
runs: [
|
||||
{
|
||||
runId: "run-hidden-recent",
|
||||
childSessionKey: hiddenSessionKey,
|
||||
requesterSessionKey: "agent:main:main",
|
||||
requesterDisplayKey: "main",
|
||||
task: "hidden recent worker",
|
||||
cleanup: "keep",
|
||||
createdAt: Date.now() - 10_000,
|
||||
startedAt: Date.now() - 10_000,
|
||||
endedAt: Date.now() - 5_000,
|
||||
outcome: { status: "ok" },
|
||||
},
|
||||
{
|
||||
runId: "run-visible-bound",
|
||||
childSessionKey: visibleSessionKey,
|
||||
requesterSessionKey: "agent:main:main",
|
||||
requesterDisplayKey: "main",
|
||||
task: "visible bound worker",
|
||||
cleanup: "keep",
|
||||
createdAt: Date.now() - 20_000,
|
||||
startedAt: Date.now() - 20_000,
|
||||
endedAt: Date.now() - 15_000,
|
||||
outcome: { status: "ok" },
|
||||
},
|
||||
],
|
||||
restTokens: [],
|
||||
} as never);
|
||||
|
||||
expect(result.reply?.text).toContain("2. visible bound worker");
|
||||
expect(result.reply?.text).not.toContain("1. visible bound worker");
|
||||
expect(result.reply?.text).not.toContain("hidden recent worker");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { getSessionBindingService } from "../../../infra/outbound/session-bindin
|
||||
import type { CommandHandlerResult } from "../commands-types.js";
|
||||
import { formatRunLabel, sortSubagentRuns } from "../subagents-utils.js";
|
||||
import {
|
||||
RECENT_WINDOW_MINUTES,
|
||||
type SubagentsCommandContext,
|
||||
resolveChannelAccountId,
|
||||
resolveCommandSurfaceChannel,
|
||||
@@ -46,12 +47,34 @@ export function handleSubagentsAgentsAction(ctx: SubagentsCommandContext): Comma
|
||||
return resolved;
|
||||
};
|
||||
|
||||
const visibleRuns: typeof runs = [];
|
||||
const dedupedRuns: typeof runs = [];
|
||||
const seenChildSessionKeys = new Set<string>();
|
||||
for (const entry of sortSubagentRuns(runs)) {
|
||||
if (seenChildSessionKeys.has(entry.childSessionKey)) {
|
||||
continue;
|
||||
}
|
||||
seenChildSessionKeys.add(entry.childSessionKey);
|
||||
dedupedRuns.push(entry);
|
||||
}
|
||||
|
||||
const recentCutoff = Date.now() - RECENT_WINDOW_MINUTES * 60_000;
|
||||
const numericOrder = [
|
||||
...dedupedRuns.filter(
|
||||
(entry) => !entry.endedAt || countPendingDescendantRuns(entry.childSessionKey) > 0,
|
||||
),
|
||||
...dedupedRuns.filter(
|
||||
(entry) =>
|
||||
entry.endedAt &&
|
||||
countPendingDescendantRuns(entry.childSessionKey) === 0 &&
|
||||
entry.endedAt >= recentCutoff,
|
||||
),
|
||||
];
|
||||
const indexByChildSessionKey = new Map(
|
||||
numericOrder.map((entry, idx) => [entry.childSessionKey, idx + 1] as const),
|
||||
);
|
||||
|
||||
const visibleRuns: typeof dedupedRuns = [];
|
||||
for (const entry of dedupedRuns) {
|
||||
const visible =
|
||||
!entry.endedAt ||
|
||||
countPendingDescendantRuns(entry.childSessionKey) > 0 ||
|
||||
@@ -59,7 +82,6 @@ export function handleSubagentsAgentsAction(ctx: SubagentsCommandContext): Comma
|
||||
if (!visible) {
|
||||
continue;
|
||||
}
|
||||
seenChildSessionKeys.add(entry.childSessionKey);
|
||||
visibleRuns.push(entry);
|
||||
}
|
||||
|
||||
@@ -67,7 +89,6 @@ export function handleSubagentsAgentsAction(ctx: SubagentsCommandContext): Comma
|
||||
if (visibleRuns.length === 0) {
|
||||
lines.push("(none)");
|
||||
} else {
|
||||
let index = 1;
|
||||
for (const entry of visibleRuns) {
|
||||
const binding = resolveSessionBindings(entry.childSessionKey)[0];
|
||||
const bindingText = binding
|
||||
@@ -78,8 +99,9 @@ export function handleSubagentsAgentsAction(ctx: SubagentsCommandContext): Comma
|
||||
: channel === "discord" || channel === "telegram"
|
||||
? "unbound"
|
||||
: "bindings available on discord/telegram";
|
||||
lines.push(`${index}. ${formatRunLabel(entry)} (${bindingText})`);
|
||||
index += 1;
|
||||
const resolvedIndex = indexByChildSessionKey.get(entry.childSessionKey);
|
||||
const prefix = resolvedIndex ? `${resolvedIndex}.` : "-";
|
||||
lines.push(`${prefix} ${formatRunLabel(entry)} (${bindingText})`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user