chore(gateway): cover denied notifyOnExit path and clarify help

This commit is contained in:
Peter Steinberger
2026-02-22 13:10:36 +01:00
parent 6fde581a25
commit d2542d9d37
2 changed files with 21 additions and 1 deletions

View File

@@ -88,7 +88,7 @@ export const FIELD_HELP: Record<string, string> = {
"Enable known poll tool no-progress loop detection (default: true).",
"tools.loopDetection.detectors.pingPong": "Enable ping-pong loop detection (default: true).",
"tools.exec.notifyOnExit":
"When true (default), backgrounded exec sessions enqueue a system event and request a heartbeat on exit.",
"When true (default), backgrounded exec sessions on exit and node exec lifecycle events enqueue a system event and request a heartbeat.",
"tools.exec.notifyOnExitEmptySuccess":
"When true, successful backgrounded exec exits with empty output still enqueue a completion system event (default: false).",
"tools.exec.pathPrepend": "Directories to prepend to PATH for exec runs (gateway/sandbox).",

View File

@@ -226,6 +226,26 @@ describe("node exec events", () => {
expect(enqueueSystemEventMock).not.toHaveBeenCalled();
expect(requestHeartbeatNowMock).not.toHaveBeenCalled();
});
it("suppresses exec.denied when notifyOnExit is false", async () => {
loadConfigMock.mockReturnValueOnce({
session: { mainKey: "agent:main:main" },
tools: { exec: { notifyOnExit: false } },
} as ReturnType<typeof loadConfig>);
const ctx = buildCtx();
await handleNodeEvent(ctx, "node-3", {
event: "exec.denied",
payloadJSON: JSON.stringify({
sessionKey: "agent:demo:main",
runId: "run-silent-3",
command: "rm -rf /",
reason: "allowlist-miss",
}),
});
expect(enqueueSystemEventMock).not.toHaveBeenCalled();
expect(requestHeartbeatNowMock).not.toHaveBeenCalled();
});
});
describe("voice transcript events", () => {