


























@@ -16,6 +16,7 @@ import {
1616requiresExecApproval,
1717} from "../infra/exec-approvals.js";
1818import type { SafeBinProfile } from "../infra/exec-safe-bin-policy.js";
19+import { INTERNAL_MESSAGE_CHANNEL, normalizeMessageChannel } from "../utils/message-channel.js";
1920import { markBackgrounded, tail } from "./bash-process-registry.js";
2021import {
2122buildExecApprovalRequesterContext,
@@ -87,6 +88,7 @@ export type ProcessGatewayAllowlistResult = {
8788execCommandOverride?: string;
8889allowWithoutEnforcedCommand?: boolean;
8990pendingResult?: AgentToolResult<ExecToolDetails>;
91+deniedResult?: AgentToolResult<ExecToolDetails>;
9092};
91939294function hasGatewayAllowlistMiss(params: {
@@ -347,6 +349,36 @@ function buildGatewayExecApprovalFollowupSummary(params: {
347349 : `Exec finished (gateway id=${params.approvalId}, session=${params.sessionId}, ${exitLabel})`;
348350}
349351352+function shouldAwaitGatewayApprovalInline(params: {
353+turnSourceChannel?: string;
354+approvalFollowupMode?: "agent" | "direct";
355+}): boolean {
356+if (params.approvalFollowupMode === "direct") {
357+return false;
358+}
359+return normalizeMessageChannel(params.turnSourceChannel) === INTERNAL_MESSAGE_CHANNEL;
360+}
361+362+function buildGatewayExecApprovalDeniedToolResult(params: {
363+approvalId: string;
364+deniedReason: string;
365+command: string;
366+cwd: string;
367+}): AgentToolResult<ExecToolDetails> {
368+const text = `Exec denied (gateway id=${params.approvalId}, ${params.deniedReason}): ${params.command}`;
369+return {
370+content: [{ type: "text", text }],
371+details: {
372+status: "failed",
373+exitCode: null,
374+durationMs: 0,
375+aggregated: text,
376+timedOut: params.deniedReason.includes("timeout"),
377+cwd: params.cwd,
378+},
379+};
380+}
381+350382async function resolveGatewayExecApprovalFollowupText(params: {
351383approvalFollowup?: ExecApprovalFollowupFactory;
352384approvalId: string;
@@ -564,31 +596,14 @@ export async function processGatewayAllowlist(
564596allowlistEval.segments[0]?.resolution ?? null,
565597params.workdir,
566598);
567-const effectiveTimeout =
568-typeof params.timeoutSec === "number" ? params.timeoutSec : params.defaultTimeoutSec;
569-const followupTarget = buildExecApprovalFollowupTarget({
570- approvalId,
571-sessionKey: params.notifySessionKey ?? params.sessionKey,
572-bashElevated: params.bashElevated,
573-turnSourceChannel: params.turnSourceChannel,
574-turnSourceTo: params.turnSourceTo,
575-turnSourceAccountId: params.turnSourceAccountId,
576-turnSourceThreadId: params.turnSourceThreadId,
577-direct: params.approvalFollowupMode === "direct",
578-});
579-580-void (async () => {
599+const resolveApprovalForExecution = async (onFailure: () => void) => {
581600const decision = await resolveApprovalDecisionOrUndefined({
582601 approvalId,
583602 preResolvedDecision,
584-onFailure: () =>
585-void sendExecApprovalFollowupResult(
586-followupTarget,
587-`Exec denied (gateway id=${approvalId}, approval-request-failed): ${params.command}`,
588-),
603+ onFailure,
589604});
590605if (decision === undefined) {
591-return;
606+return { deniedReason: "approval-request-failed", requestFailed: true };
592607}
593608594609const {
@@ -647,10 +662,58 @@ export async function processGatewayAllowlist(
647662deniedReason = deniedReason ?? "allowlist-miss";
648663}
649664650-if (deniedReason) {
665+return { deniedReason, requestFailed: false };
666+};
667+668+if (unavailableReason === null && shouldAwaitGatewayApprovalInline(params)) {
669+const approvalDecision = await resolveApprovalForExecution(() => undefined);
670+if (approvalDecision.deniedReason) {
671+return {
672+deniedResult: buildGatewayExecApprovalDeniedToolResult({
673+ approvalId,
674+deniedReason: approvalDecision.deniedReason,
675+command: params.command,
676+cwd: params.workdir,
677+}),
678+};
679+}
680+681+recordMatchedAllowlistUse(resolvedPath ?? undefined);
682+return {
683+execCommandOverride: enforcedCommand,
684+allowWithoutEnforcedCommand: enforcedCommand === undefined,
685+};
686+}
687+688+const effectiveTimeout =
689+typeof params.timeoutSec === "number" ? params.timeoutSec : params.defaultTimeoutSec;
690+const followupTarget = buildExecApprovalFollowupTarget({
691+ approvalId,
692+sessionKey: params.notifySessionKey ?? params.sessionKey,
693+bashElevated: params.bashElevated,
694+turnSourceChannel: params.turnSourceChannel,
695+turnSourceTo: params.turnSourceTo,
696+turnSourceAccountId: params.turnSourceAccountId,
697+turnSourceThreadId: params.turnSourceThreadId,
698+direct: params.approvalFollowupMode === "direct",
699+});
700+701+void (async () => {
702+const approvalDecision = await resolveApprovalForExecution(
703+() =>
704+void sendExecApprovalFollowupResult(
705+followupTarget,
706+`Exec denied (gateway id=${approvalId}, approval-request-failed): ${params.command}`,
707+),
708+);
709+if (approvalDecision.requestFailed) {
710+return;
711+}
712+713+if (approvalDecision.deniedReason) {
651714await sendExecApprovalFollowupResult(
652715followupTarget,
653-`Exec denied (gateway id=${approvalId}, ${deniedReason}): ${params.command}`,
716+`Exec denied (gateway id=${approvalId}, ${approvalDecision.deniedReason}): ${params.command}`,
654717);
655718return;
656719}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。