




















@@ -4,10 +4,7 @@
44 * and lazy command highlighting for host/node approval payloads.
55 */
66import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
7-import {
8-DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS,
9-DEFAULT_APPROVAL_TIMEOUT_MS,
10-} from "./bash-tools.exec-runtime.js";
7+import { DEFAULT_APPROVAL_TIMEOUT_MS } from "./bash-tools.exec-runtime.js";
118129const commandExplainerMock = vi.hoisted(() => ({
1310importCount: 0,
@@ -42,7 +39,6 @@ vi.mock("./tools/gateway.js", () => ({
42394340let callGatewayTool: typeof import("./tools/gateway.js").callGatewayTool;
4441let registerExecApprovalRequest: typeof import("./bash-tools.exec-approval-request.js").registerExecApprovalRequest;
45-let requestExecApprovalDecision: typeof import("./bash-tools.exec-approval-request.js").requestExecApprovalDecision;
4642let registerExecApprovalRequestForHost: typeof import("./bash-tools.exec-approval-request.js").registerExecApprovalRequestForHost;
47434844const initialProcessPlatform = Object.getOwnPropertyDescriptor(process, "platform");
@@ -75,14 +71,11 @@ function requireApprovalRequestPayload(callIndex: number): ApprovalRequestPayloa
7571return payload as ApprovalRequestPayload;
7672}
777378-describe("requestExecApprovalDecision", () => {
74+describe("exec approval requests", () => {
7975beforeAll(async () => {
8076({ callGatewayTool } = await import("./tools/gateway.js"));
81-({
82- registerExecApprovalRequest,
83- requestExecApprovalDecision,
84- registerExecApprovalRequestForHost,
85-} = await import("./bash-tools.exec-approval-request.js"));
77+({ registerExecApprovalRequest, registerExecApprovalRequestForHost } =
78+await import("./bash-tools.exec-approval-request.js"));
8679});
87808881beforeEach(() => {
@@ -100,190 +93,6 @@ describe("requestExecApprovalDecision", () => {
10093expect(commandExplainerMock.importCount).toBe(0);
10194});
10295103-it("returns string decisions", async () => {
104-vi.mocked(callGatewayTool)
105-.mockResolvedValueOnce({
106-status: "accepted",
107-id: "approval-id",
108-expiresAtMs: DEFAULT_APPROVAL_TIMEOUT_MS,
109-})
110-.mockResolvedValueOnce({ decision: "allow-once" });
111-112-const result = await requestExecApprovalDecision({
113-id: "approval-id",
114-command: "echo hi",
115-cwd: "/tmp",
116-host: "gateway",
117-security: "allowlist",
118-ask: "always",
119-agentId: "main",
120-resolvedPath: "/usr/bin/echo",
121-sessionKey: "session",
122-turnSourceChannel: "whatsapp",
123-turnSourceTo: "+15555550123",
124-turnSourceAccountId: "work",
125-turnSourceThreadId: "1739201675.123",
126-});
127-128-expect(result).toBe("allow-once");
129-expect(callGatewayTool).toHaveBeenCalledWith(
130-"exec.approval.request",
131-{ timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS },
132-{
133-id: "approval-id",
134-command: "echo hi",
135-cwd: "/tmp",
136-nodeId: undefined,
137-host: "gateway",
138-security: "allowlist",
139-ask: "always",
140-agentId: "main",
141-resolvedPath: "/usr/bin/echo",
142-sessionKey: "session",
143-turnSourceChannel: "whatsapp",
144-turnSourceTo: "+15555550123",
145-turnSourceAccountId: "work",
146-turnSourceThreadId: "1739201675.123",
147-timeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS,
148-twoPhase: true,
149-},
150-{ expectFinal: false },
151-);
152-expect(callGatewayTool).toHaveBeenNthCalledWith(
153-2,
154-"exec.approval.waitDecision",
155-{ timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS },
156-{ id: "approval-id" },
157-);
158-});
159-160-it("returns null for missing or non-string decisions", async () => {
161-vi.mocked(callGatewayTool)
162-.mockResolvedValueOnce({ status: "accepted", id: "approval-id", expiresAtMs: 1234 })
163-.mockResolvedValueOnce({});
164-await expect(
165-requestExecApprovalDecision({
166-id: "approval-id",
167-command: "echo hi",
168-cwd: "/tmp",
169-nodeId: "node-1",
170-host: "node",
171-security: "allowlist",
172-ask: "on-miss",
173-}),
174-).resolves.toBeNull();
175-176-vi.mocked(callGatewayTool)
177-.mockResolvedValueOnce({ status: "accepted", id: "approval-id-2", expiresAtMs: 1234 })
178-.mockResolvedValueOnce({ decision: 123 });
179-await expect(
180-requestExecApprovalDecision({
181-id: "approval-id-2",
182-command: "echo hi",
183-cwd: "/tmp",
184-nodeId: "node-1",
185-host: "node",
186-security: "allowlist",
187-ask: "on-miss",
188-}),
189-).resolves.toBeNull();
190-});
191-192-it("uses registration response id when waiting for decision", async () => {
193-vi.mocked(callGatewayTool)
194-.mockResolvedValueOnce({
195-status: "accepted",
196-id: "server-assigned-id",
197-expiresAtMs: DEFAULT_APPROVAL_TIMEOUT_MS,
198-})
199-.mockResolvedValueOnce({ decision: "allow-once" });
200-201-await expect(
202-requestExecApprovalDecision({
203-id: "client-id",
204-command: "echo hi",
205-cwd: "/tmp",
206-host: "gateway",
207-security: "allowlist",
208-ask: "on-miss",
209-}),
210-).resolves.toBe("allow-once");
211-212-expect(callGatewayTool).toHaveBeenNthCalledWith(
213-2,
214-"exec.approval.waitDecision",
215-{ timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS },
216-{ id: "server-assigned-id" },
217-);
218-});
219-220-it("treats expired-or-missing waitDecision as null decision", async () => {
221-vi.mocked(callGatewayTool)
222-.mockResolvedValueOnce({
223-status: "accepted",
224-id: "approval-id",
225-expiresAtMs: DEFAULT_APPROVAL_TIMEOUT_MS,
226-})
227-.mockRejectedValueOnce(new Error("approval expired or not found"));
228-229-await expect(
230-requestExecApprovalDecision({
231-id: "approval-id",
232-command: "echo hi",
233-cwd: "/tmp",
234-host: "gateway",
235-security: "allowlist",
236-ask: "on-miss",
237-}),
238-).resolves.toBeNull();
239-});
240-241-it("returns final decision directly when gateway already replies with decision", async () => {
242-vi.mocked(callGatewayTool).mockResolvedValue({ decision: "deny", id: "approval-id" });
243-244-const result = await requestExecApprovalDecision({
245-id: "approval-id",
246-command: "echo hi",
247-cwd: "/tmp",
248-host: "gateway",
249-security: "allowlist",
250-ask: "on-miss",
251-});
252-253-expect(result).toBe("deny");
254-expect(vi.mocked(callGatewayTool).mock.calls).toStrictEqual([
255-[
256-"exec.approval.request",
257-{ timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS },
258-{
259-ask: "on-miss",
260-command: "echo hi",
261-commandSpans: undefined,
262-cwd: "/tmp",
263-env: undefined,
264-host: "gateway",
265-id: "approval-id",
266-nodeId: undefined,
267-requireDeliveryRoute: undefined,
268-resolvedPath: undefined,
269-security: "allowlist",
270-sessionKey: undefined,
271-suppressDelivery: undefined,
272-systemRunPlan: undefined,
273-timeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS,
274-twoPhase: true,
275-turnSourceAccountId: undefined,
276-turnSourceChannel: undefined,
277-turnSourceThreadId: undefined,
278-turnSourceTo: undefined,
279-warningText: undefined,
280-agentId: undefined,
281-},
282-{ expectFinal: false },
283-],
284-]);
285-});
286-28796it("bounds missing registration expiries when the process clock is invalid", async () => {
28897vi.mocked(callGatewayTool).mockResolvedValue({ id: "approval-id" });
28998const dateNow = vi.spyOn(Date, "now").mockReturnValue(Number.NaN);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。