fix(cli): don't force localhost gateway url in remote mode

Fixes remote gateway setup (remote mode) by not overriding url; adds regression tests. Thanks @oswalpalash.
This commit is contained in:
Palash Oswal
2026-01-06 09:30:45 -05:00
committed by GitHub
parent 5aa1ed2c96
commit b91012b697
6 changed files with 130 additions and 3 deletions

View File

@@ -0,0 +1,31 @@
import { describe, expect, it, vi } from "vitest";
import { callGatewayTool, resolveGatewayOptions } from "./gateway.js";
const callGatewayMock = vi.fn();
vi.mock("../../gateway/call.js", () => ({
callGateway: (...args: unknown[]) => callGatewayMock(...args),
}));
describe("gateway tool defaults", () => {
it("leaves url undefined so callGateway can use config", () => {
const opts = resolveGatewayOptions();
expect(opts.url).toBeUndefined();
});
it("passes through explicit overrides", async () => {
callGatewayMock.mockResolvedValueOnce({ ok: true });
await callGatewayTool(
"health",
{ gatewayUrl: "ws://example", gatewayToken: "t", timeoutMs: 5000 },
{},
);
expect(callGatewayMock).toHaveBeenCalledWith(
expect.objectContaining({
url: "ws://example",
token: "t",
timeoutMs: 5000,
}),
);
});
});

View File

@@ -9,10 +9,11 @@ export type GatewayCallOptions = {
};
export function resolveGatewayOptions(opts?: GatewayCallOptions) {
// Prefer an explicit override; otherwise let callGateway choose based on config.
const url =
typeof opts?.gatewayUrl === "string" && opts.gatewayUrl.trim()
? opts.gatewayUrl.trim()
: DEFAULT_GATEWAY_URL;
: undefined;
const token =
typeof opts?.gatewayToken === "string" && opts.gatewayToken.trim()
? opts.gatewayToken.trim()

77
src/commands/poll.test.ts Normal file
View File

@@ -0,0 +1,77 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { CliDeps } from "../cli/deps.js";
import { pollCommand } from "./poll.js";
let testConfig: Record<string, unknown> = {};
vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../config/config.js")>();
return {
...actual,
loadConfig: () => testConfig,
};
});
const callGatewayMock = vi.fn();
vi.mock("../gateway/call.js", () => ({
callGateway: (...args: unknown[]) => callGatewayMock(...args),
randomIdempotencyKey: () => "idem-1",
}));
const runtime = {
log: vi.fn(),
error: vi.fn(),
exit: vi.fn(),
};
const deps: CliDeps = {
sendMessageWhatsApp: vi.fn(),
sendMessageTelegram: vi.fn(),
sendMessageDiscord: vi.fn(),
sendMessageSlack: vi.fn(),
sendMessageSignal: vi.fn(),
sendMessageIMessage: vi.fn(),
};
describe("pollCommand", () => {
beforeEach(() => {
callGatewayMock.mockReset();
testConfig = {};
});
it("routes through gateway", async () => {
callGatewayMock.mockResolvedValueOnce({ messageId: "p1" });
await pollCommand(
{
to: "+1",
question: "hi?",
option: ["y", "n"],
},
deps,
runtime,
);
expect(callGatewayMock).toHaveBeenCalledWith(
expect.objectContaining({ method: "poll" }),
);
});
it("does not override remote gateway URL", async () => {
callGatewayMock.mockResolvedValueOnce({ messageId: "p1" });
testConfig = {
gateway: { mode: "remote", remote: { url: "wss://remote.example" } },
};
await pollCommand(
{
to: "+1",
question: "hi?",
option: ["y", "n"],
},
deps,
runtime,
);
const args = callGatewayMock.mock.calls.at(-1)?.[0] as
| Record<string, unknown>
| undefined;
expect(args?.url).toBeUndefined();
});
});

View File

@@ -57,7 +57,6 @@ export async function pollCommand(
toJid?: string;
channelId?: string;
}>({
url: "ws://127.0.0.1:18789",
method: "poll",
params: {
to: opts.to,

View File

@@ -81,6 +81,26 @@ describe("sendCommand", () => {
expect(runtime.log).toHaveBeenCalledWith(expect.stringContaining("g1"));
});
it("does not override remote gateway URL", async () => {
callGatewayMock.mockResolvedValueOnce({ messageId: "g2" });
testConfig = {
gateway: { mode: "remote", remote: { url: "wss://remote.example" } },
};
const deps = makeDeps();
await sendCommand(
{
to: "+1",
message: "hi",
},
deps,
runtime,
);
const args = callGatewayMock.mock.calls.at(-1)?.[0] as
| Record<string, unknown>
| undefined;
expect(args?.url).toBeUndefined();
});
it("passes gifPlayback to gateway send", async () => {
callGatewayMock.mockClear();
callGatewayMock.mockResolvedValueOnce({ messageId: "g1" });

View File

@@ -167,7 +167,6 @@ export async function sendCommand(
callGateway<{
messageId: string;
}>({
url: "ws://127.0.0.1:18789",
method: "send",
params: {
to: opts.to,