Files
openclaw/src/agents/subagent-spawn-lifecycle.ts
T
Peter Steinberger 5284408470 refactor(agents): split subagent-spawn and drop its max-lines baseline entry (#114030)
* refactor(agents): split subagent spawn helpers

* refactor(agents): keep spawn agent state caller-owned

* refactor(agents): keep relocated subagent-spawn symbols module-private
2026-07-26 01:12:07 -04:00

79 lines
2.6 KiB
TypeScript

import type { SubagentLifecycleHookRunner } from "../plugins/hooks.js";
import type { DeliveryContext } from "../utils/delivery-context.types.js";
import type { SpawnSubagentMode } from "./subagent-spawn.types.js";
export function createSubagentSpawnLifecycleEmitter(params: {
hookRunner: SubagentLifecycleHookRunner | null;
childSessionKey: string;
requesterInternalKey: string;
progressOrigin: {
channel?: string;
accountId?: string;
to?: string;
threadId?: string | number;
channelId?: string;
messageId?: string | number;
};
targetAgentId: string;
label?: string;
requesterOrigin?: DeliveryContext;
requestThreadBinding: boolean;
spawnMode: SpawnSubagentMode;
resolvedModelMetadata: {
resolvedModel?: string;
resolvedProvider?: string;
};
}): (hookRunId: string) => Promise<void> {
// "spawned"/"started" hooks mean an accepted Gateway run. Direct runs emit
// after the shared pipeline; queued collectors emit from the scheduler start.
return async (hookRunId: string) => {
if (params.hookRunner?.hasHooks("subagent_progress")) {
try {
await params.hookRunner.runSubagentProgress(
{
phase: "started",
runId: hookRunId,
childSessionKey: params.childSessionKey,
requester: params.progressOrigin,
},
{
runId: hookRunId,
childSessionKey: params.childSessionKey,
requesterSessionKey: params.requesterInternalKey,
},
);
} catch {
// Presentation hooks are best-effort after durable registration.
}
}
if (params.hookRunner?.hasHooks("subagent_spawned")) {
try {
await params.hookRunner.runSubagentSpawned(
{
runId: hookRunId,
childSessionKey: params.childSessionKey,
agentId: params.targetAgentId,
label: params.label,
requester: {
channel: params.requesterOrigin?.channel,
accountId: params.requesterOrigin?.accountId,
to: params.requesterOrigin?.to,
threadId: params.requesterOrigin?.threadId,
},
threadRequested: params.requestThreadBinding,
mode: params.spawnMode,
...params.resolvedModelMetadata,
},
{
runId: hookRunId,
childSessionKey: params.childSessionKey,
requesterSessionKey: params.requesterInternalKey,
},
);
} catch {
// Spawn stays accepted if lifecycle presentation fails.
}
}
};
}