

















@@ -1,6 +1,11 @@
11import path from "node:path";
22import type { AgentToolResult } from "@earendil-works/pi-agent-core";
33import { emitDiagnosticEvent } from "../infra/diagnostic-events.js";
4+import {
5+type EventSessionRoutingPolicy,
6+resolveEventSessionKeyForPolicy,
7+scopedHeartbeatWakeOptionsForPolicy,
8+} from "../infra/event-session-routing.js";
49import {
510DEFAULT_EXEC_APPROVAL_TIMEOUT_MS,
611resolveExecApprovalAllowedDecisions,
@@ -12,7 +17,6 @@ import { requestHeartbeat } from "../infra/heartbeat-wake.js";
1217import { isDangerousHostInheritedEnvVarName } from "../infra/host-env-security.js";
1318import { findPathKey, mergePathPrepend, removePathPrepend } from "../infra/path-prepend.js";
1419import { enqueueSystemEvent } from "../infra/system-events.js";
15-import { resolveEventSessionKey, scopedHeartbeatWakeOptions } from "../routing/session-key.js";
1620import { isSubagentSessionKey } from "../sessions/session-key-utils.js";
1721import type { ProcessSession } from "./bash-process-registry.js";
1822import type { ExecToolDetails } from "./bash-tools.exec-types.js";
@@ -340,24 +344,27 @@ function maybeNotifyOnExit(session: ProcessSession, status: "completed" | "faile
340344const summary = output
341345 ? `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel}) :: ${output}`
342346 : `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel})`;
347+const eventRouting = session.eventRouting ?? {
348+mainKey: session.mainKey,
349+sessionScope: session.sessionScope,
350+};
343351enqueueSystemEvent(summary, {
344-sessionKey: resolveEventSessionKey(sessionKey, session.mainKey, session.sessionScope),
352+sessionKey: resolveEventSessionKeyForPolicy(sessionKey, eventRouting),
345353deliveryContext: session.notifyDeliveryContext,
346354});
347355// Subagent sessions receive exec results via process poll and announce flow;
348356// the heartbeat would fall back to the main session and cause spurious wakes.
349357if (!isSubagentSessionKey(sessionKey)) {
350358requestHeartbeat(
351-scopedHeartbeatWakeOptions(
359+scopedHeartbeatWakeOptionsForPolicy(
352360sessionKey,
353361{
354362source: "exec-event",
355363intent: "event",
356364reason: "exec-event",
357365coalesceMs: 0,
358366},
359-session.mainKey,
360-session.sessionScope,
367+eventRouting,
361368),
362369);
363370}
@@ -435,31 +442,35 @@ export function emitExecSystemEvent(
435442/** `session.scope` from the runtime config; needed so global-scope
436443 * agents route cron-run events to the "global" queue. */
437444sessionScope?: "per-sender" | "global";
445+eventRouting?: EventSessionRoutingPolicy;
438446},
439447) {
440448const sessionKey = opts.sessionKey?.trim();
441449if (!sessionKey) {
442450return;
443451}
452+const eventRouting = opts.eventRouting ?? {
453+mainKey: opts.mainKey,
454+sessionScope: opts.sessionScope,
455+};
444456enqueueSystemEvent(text, {
445-sessionKey: resolveEventSessionKey(sessionKey, opts.mainKey, opts.sessionScope),
457+sessionKey: resolveEventSessionKeyForPolicy(sessionKey, eventRouting),
446458contextKey: opts.contextKey,
447459deliveryContext: opts.deliveryContext,
448460});
449461// Subagent sessions receive exec results via process poll and announce flow;
450462// the heartbeat would fall back to the main session and cause spurious wakes.
451463if (!isSubagentSessionKey(sessionKey)) {
452464requestHeartbeat(
453-scopedHeartbeatWakeOptions(
465+scopedHeartbeatWakeOptionsForPolicy(
454466sessionKey,
455467{
456468source: "exec-event",
457469intent: "event",
458470reason: "exec-event",
459471coalesceMs: 0,
460472},
461-opts.mainKey,
462-opts.sessionScope,
473+eventRouting,
463474),
464475);
465476}
@@ -636,6 +647,8 @@ export async function runExecProcess(opts: {
636647 * `mainKey` so the cron-run remap can route global-scope agents to
637648 * the "global" queue instead of agent-main. */
638649sessionScope?: "per-sender" | "global";
650+/** Start-time routing policy for detached exec system events. */
651+eventRouting?: EventSessionRoutingPolicy;
639652notifyDeliveryContext?: DeliveryContext;
640653timeoutSec: number | null;
641654onUpdate?: (partialResult: AgentToolResult<ExecToolDetails>) => void;
@@ -657,6 +670,7 @@ export async function runExecProcess(opts: {
657670sessionKey: opts.sessionKey,
658671mainKey: opts.mainKey,
659672sessionScope: opts.sessionScope,
673+eventRouting: opts.eventRouting,
660674notifyDeliveryContext: normalizeDeliveryContext(opts.notifyDeliveryContext),
661675notifyOnExit: opts.notifyOnExit,
662676notifyOnExitEmptySuccess: opts.notifyOnExitEmptySuccess === true,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。