File size: 2,637 Bytes
4c76b0d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 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.
}
}
};
}
|