
















@@ -101,6 +101,19 @@ function createGatewayTimeoutError() {
101101});
102102}
103103104+function createGatewayClosedError() {
105+const err = new Error("gateway closed before response");
106+err.name = "GatewayTransportError";
107+return Object.assign(err, {
108+kind: "closed",
109+connectionDetails: {
110+url: "ws://127.0.0.1:18789",
111+urlSource: "local loopback",
112+message: "Gateway target: ws://127.0.0.1:18789",
113+},
114+});
115+}
116+104117vi.mock("../config/config.js", () => ({ getRuntimeConfig: loadConfig, loadConfig }));
105118vi.mock("../gateway/call.js", () => ({
106119 callGateway,
@@ -222,7 +235,7 @@ describe("agentCliCommand", () => {
222235223236it("falls back to embedded agent when gateway fails", async () => {
224237await withTempStore(async () => {
225-callGateway.mockRejectedValue(new Error("gateway not connected"));
238+callGateway.mockRejectedValue(createGatewayClosedError());
226239mockLocalAgentReply();
227240228241await agentCliCommand({ message: "hi", to: "+1555" }, runtime);
@@ -242,6 +255,25 @@ describe("agentCliCommand", () => {
242255});
243256});
244257258+it("does not fall back to embedded agent for gateway request errors", async () => {
259+await withTempStore(async () => {
260+callGateway.mockRejectedValue(
261+Object.assign(new Error("missing scope: operator.admin"), {
262+name: "GatewayClientRequestError",
263+gatewayCode: "INVALID_REQUEST",
264+}),
265+);
266+267+await expect(agentCliCommand({ message: "hi", to: "+1555" }, runtime)).rejects.toThrow(
268+"missing scope: operator.admin",
269+);
270+271+expect(callGateway).toHaveBeenCalledTimes(1);
272+expect(agentCommand).not.toHaveBeenCalled();
273+expect(runtime.error).not.toHaveBeenCalledWith(expect.stringContaining("EMBEDDED FALLBACK"));
274+});
275+});
276+245277it("uses a fresh embedded session when gateway agent times out", async () => {
246278await withTempStore(async () => {
247279callGateway.mockRejectedValue(createGatewayTimeoutError());
@@ -311,7 +343,7 @@ describe("agentCliCommand", () => {
311343312344it("passes fallback metadata into JSON embedded fallback output", async () => {
313345await withTempStore(async () => {
314-callGateway.mockRejectedValue(new Error("gateway not connected"));
346+callGateway.mockRejectedValue(createGatewayClosedError());
315347agentCommand.mockImplementationOnce(async (opts, rt) => {
316348expect(loggingState.forceConsoleToStderr).toBe(true);
317349const resultMetaOverrides = (
@@ -399,7 +431,7 @@ describe("agentCliCommand", () => {
399431400432it("forces bundle MCP cleanup on embedded fallback", async () => {
401433await withTempStore(async () => {
402-callGateway.mockRejectedValue(new Error("gateway not connected"));
434+callGateway.mockRejectedValue(createGatewayClosedError());
403435mockLocalAgentReply();
404436405437await agentCliCommand({ message: "hi", to: "+1555" }, runtime);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。