diff --git a/src/agents/subagent-registry-announce-read.ts b/src/agents/subagent-registry-announce-read.ts index da1908aa005..147cb4113cb 100644 --- a/src/agents/subagent-registry-announce-read.ts +++ b/src/agents/subagent-registry-announce-read.ts @@ -3,7 +3,7 @@ import { subagentRuns } from "./subagent-registry-memory.js"; import { countPendingDescendantRunsExcludingRunFromRuns, countPendingDescendantRunsFromRuns, - findRunIdsByChildSessionKeyFromRuns, + isSubagentSessionRunActiveFromRuns, listRunsForRequesterFromRuns, resolveRequesterForChildSessionFromRuns, shouldIgnorePostCompletionAnnounceForSessionFromRuns, @@ -29,18 +29,7 @@ export function resolveRequesterForChildSession(childSessionKey: string): { } export function isSubagentSessionRunActive(childSessionKey: string): boolean { - const runIds = findRunIdsByChildSessionKeyFromRuns(subagentRuns, childSessionKey); - let latest: SubagentRunRecord | undefined; - for (const runId of runIds) { - const entry = subagentRuns.get(runId); - if (!entry) { - continue; - } - if (!latest || entry.createdAt > latest.createdAt) { - latest = entry; - } - } - return Boolean(latest && typeof latest.endedAt !== "number"); + return isSubagentSessionRunActiveFromRuns(subagentRuns, childSessionKey); } export function shouldIgnorePostCompletionAnnounceForSession(childSessionKey: string): boolean { diff --git a/src/agents/subagent-registry-queries.ts b/src/agents/subagent-registry-queries.ts index f6af4e81615..3e7b8ee373c 100644 --- a/src/agents/subagent-registry-queries.ts +++ b/src/agents/subagent-registry-queries.ts @@ -86,6 +86,43 @@ function findLatestRunForChildSession( return latest; } +export function isSubagentSessionRunActiveFromRuns( + runs: Map, + childSessionKey: string, +): boolean { + const latest = findLatestRunForChildSession(runs, childSessionKey); + return Boolean(latest && typeof latest.endedAt !== "number"); +} + +export function getSubagentRunByChildSessionKeyFromRuns( + runs: Map, + childSessionKey: string, +): SubagentRunRecord | null { + const key = childSessionKey.trim(); + if (!key) { + return null; + } + + let latestActive: SubagentRunRecord | null = null; + let latestEnded: SubagentRunRecord | null = null; + for (const entry of runs.values()) { + if (entry.childSessionKey !== key) { + continue; + } + if (typeof entry.endedAt !== "number") { + if (!latestActive || entry.createdAt > latestActive.createdAt) { + latestActive = entry; + } + continue; + } + if (!latestEnded || entry.createdAt > latestEnded.createdAt) { + latestEnded = entry; + } + } + + return latestActive ?? latestEnded; +} + export function resolveRequesterForChildSessionFromRuns( runs: Map, childSessionKey: string, diff --git a/src/agents/subagent-registry-read.ts b/src/agents/subagent-registry-read.ts index c3f1defd81d..95f16c1d283 100644 --- a/src/agents/subagent-registry-read.ts +++ b/src/agents/subagent-registry-read.ts @@ -1,6 +1,7 @@ import { subagentRuns } from "./subagent-registry-memory.js"; import { countActiveDescendantRunsFromRuns, + getSubagentRunByChildSessionKeyFromRuns, listDescendantRunsForRequesterFromRuns, listRunsForControllerFromRuns, } from "./subagent-registry-queries.js"; @@ -40,29 +41,10 @@ export function listDescendantRunsForRequester(rootSessionKey: string): Subagent } export function getSubagentRunByChildSessionKey(childSessionKey: string): SubagentRunRecord | null { - const key = childSessionKey.trim(); - if (!key) { - return null; - } - - let latestActive: SubagentRunRecord | null = null; - let latestEnded: SubagentRunRecord | null = null; - for (const entry of getSubagentRunsSnapshotForRead(subagentRuns).values()) { - if (entry.childSessionKey !== key) { - continue; - } - if (typeof entry.endedAt !== "number") { - if (!latestActive || entry.createdAt > latestActive.createdAt) { - latestActive = entry; - } - continue; - } - if (!latestEnded || entry.createdAt > latestEnded.createdAt) { - latestEnded = entry; - } - } - - return latestActive ?? latestEnded; + return getSubagentRunByChildSessionKeyFromRuns( + getSubagentRunsSnapshotForRead(subagentRuns), + childSessionKey, + ); } export function getSessionDisplaySubagentRunByChildSessionKey( diff --git a/src/agents/subagent-registry-run-manager.ts b/src/agents/subagent-registry-run-manager.ts index 71573306643..63c3cac401f 100644 --- a/src/agents/subagent-registry-run-manager.ts +++ b/src/agents/subagent-registry-run-manager.ts @@ -31,6 +31,26 @@ function shouldDeleteAttachments(entry: SubagentRunRecord) { return entry.cleanup === "delete" || !entry.retainAttachmentsOnKeep; } +export type RegisterSubagentRunParams = { + runId: string; + childSessionKey: string; + controllerSessionKey?: string; + requesterSessionKey: string; + requesterOrigin?: DeliveryContext; + requesterDisplayKey: string; + task: string; + cleanup: "delete" | "keep"; + label?: string; + model?: string; + workspaceDir?: string; + runTimeoutSeconds?: number; + expectsCompletionMessage?: boolean; + spawnMode?: "run" | "session"; + attachmentsDir?: string; + attachmentsRootDir?: string; + retainAttachmentsOnKeep?: boolean; +}; + export function createSubagentRunManager(params: { runs: Map; resumedRuns: Set; @@ -261,25 +281,7 @@ export function createSubagentRunManager(params: { return true; }; - const registerSubagentRun = (registerParams: { - runId: string; - childSessionKey: string; - controllerSessionKey?: string; - requesterSessionKey: string; - requesterOrigin?: DeliveryContext; - requesterDisplayKey: string; - task: string; - cleanup: "delete" | "keep"; - label?: string; - model?: string; - workspaceDir?: string; - runTimeoutSeconds?: number; - expectsCompletionMessage?: boolean; - spawnMode?: "run" | "session"; - attachmentsDir?: string; - attachmentsRootDir?: string; - retainAttachmentsOnKeep?: boolean; - }) => { + const registerSubagentRun = (registerParams: RegisterSubagentRunParams) => { const runId = registerParams.runId.trim(); const childSessionKey = registerParams.childSessionKey.trim(); const requesterSessionKey = registerParams.requesterSessionKey.trim(); diff --git a/src/agents/subagent-registry.ts b/src/agents/subagent-registry.ts index 21ed36cc093..2eac8e8c97c 100644 --- a/src/agents/subagent-registry.ts +++ b/src/agents/subagent-registry.ts @@ -38,14 +38,18 @@ import { countActiveRunsForSessionFromRuns, countPendingDescendantRunsExcludingRunFromRuns, countPendingDescendantRunsFromRuns, - findRunIdsByChildSessionKeyFromRuns, + getSubagentRunByChildSessionKeyFromRuns, + isSubagentSessionRunActiveFromRuns, listRunsForControllerFromRuns, listDescendantRunsForRequesterFromRuns, listRunsForRequesterFromRuns, resolveRequesterForChildSessionFromRuns, shouldIgnorePostCompletionAnnounceForSessionFromRuns, } from "./subagent-registry-queries.js"; -import { createSubagentRunManager } from "./subagent-registry-run-manager.js"; +import { + createSubagentRunManager, + type RegisterSubagentRunParams, +} from "./subagent-registry-run-manager.js"; import { getSubagentRunsSnapshotForRead, persistSubagentRunsToDisk, @@ -723,25 +727,7 @@ export function replaceSubagentRunAfterSteer(params: { return subagentRunManager.replaceSubagentRunAfterSteer(params); } -export function registerSubagentRun(params: { - runId: string; - childSessionKey: string; - controllerSessionKey?: string; - requesterSessionKey: string; - requesterOrigin?: DeliveryContext; - requesterDisplayKey: string; - task: string; - cleanup: "delete" | "keep"; - label?: string; - model?: string; - workspaceDir?: string; - runTimeoutSeconds?: number; - expectsCompletionMessage?: boolean; - spawnMode?: "run" | "session"; - attachmentsDir?: string; - attachmentsRootDir?: string; - retainAttachmentsOnKeep?: boolean; -}) { +export function registerSubagentRun(params: RegisterSubagentRunParams) { subagentRunManager.registerSubagentRun(params); } @@ -791,10 +777,6 @@ export function releaseSubagentRun(runId: string) { subagentRunManager.releaseSubagentRun(runId); } -function findRunIdsByChildSessionKey(childSessionKey: string): string[] { - return findRunIdsByChildSessionKeyFromRuns(subagentRuns, childSessionKey); -} - export function resolveRequesterForChildSession(childSessionKey: string): { requesterSessionKey: string; requesterOrigin?: DeliveryContext; @@ -813,18 +795,7 @@ export function resolveRequesterForChildSession(childSessionKey: string): { } export function isSubagentSessionRunActive(childSessionKey: string): boolean { - const runIds = findRunIdsByChildSessionKey(childSessionKey); - let latest: SubagentRunRecord | undefined; - for (const runId of runIds) { - const entry = subagentRuns.get(runId); - if (!entry) { - continue; - } - if (!latest || entry.createdAt > latest.createdAt) { - latest = entry; - } - } - return Boolean(latest && typeof latest.endedAt !== "number"); + return isSubagentSessionRunActiveFromRuns(subagentRuns, childSessionKey); } export function shouldIgnorePostCompletionAnnounceForSession(childSessionKey: string): boolean { @@ -896,29 +867,10 @@ export function listDescendantRunsForRequester(rootSessionKey: string): Subagent } export function getSubagentRunByChildSessionKey(childSessionKey: string): SubagentRunRecord | null { - const key = childSessionKey.trim(); - if (!key) { - return null; - } - - let latestActive: SubagentRunRecord | null = null; - let latestEnded: SubagentRunRecord | null = null; - for (const entry of subagentRegistryDeps.getSubagentRunsSnapshotForRead(subagentRuns).values()) { - if (entry.childSessionKey !== key) { - continue; - } - if (typeof entry.endedAt !== "number") { - if (!latestActive || entry.createdAt > latestActive.createdAt) { - latestActive = entry; - } - continue; - } - if (!latestEnded || entry.createdAt > latestEnded.createdAt) { - latestEnded = entry; - } - } - - return latestActive ?? latestEnded; + return getSubagentRunByChildSessionKeyFromRuns( + subagentRegistryDeps.getSubagentRunsSnapshotForRead(subagentRuns), + childSessionKey, + ); } export function getLatestSubagentRunByChildSessionKey(