import { describe, expect, it, vi } from "vitest"; import { isWebchatSessionMutationBlockedError, syncGatewaySessionSettings, } from "@/lib/gateway/GatewayClient"; import type { GatewayClient } from "@/lib/gateway/GatewayClient"; import { GatewayResponseError } from "@/lib/gateway/errors"; describe("session settings sync helper", () => { it("detects webchat session mutation blocked gateway errors", () => { const blocked = new GatewayResponseError({ code: "INVALID_REQUEST", message: "webchat clients cannot patch sessions; use chat.send for session-scoped updates", }); expect(isWebchatSessionMutationBlockedError(blocked)).toBe(true); }); it("does not misclassify unrelated invalid request errors", () => { const invalid = new GatewayResponseError({ code: "INVALID_REQUEST", message: "invalid model ref", }); expect(isWebchatSessionMutationBlockedError(invalid)).toBe(false); }); it("does not misclassify non-gateway errors", () => { expect( isWebchatSessionMutationBlockedError( new Error("webchat clients cannot patch sessions; use chat.send for session-scoped updates") ) ).toBe(false); }); it("throws when session key is missing", async () => { const client = { call: vi.fn() } as unknown as GatewayClient; await expect( syncGatewaySessionSettings({ client, sessionKey: "", model: "openai/gpt-5", }) ).rejects.toThrow("Session key is required."); }); it("throws when no settings are provided", async () => { const client = { call: vi.fn() } as unknown as GatewayClient; await expect( syncGatewaySessionSettings({ client, sessionKey: "agent:1:studio:abc", }) ).rejects.toThrow("At least one session setting must be provided."); }); it("patches model and thinking level together", async () => { const client = { call: vi.fn(async () => ({ ok: true })), } as unknown as GatewayClient; await syncGatewaySessionSettings({ client, sessionKey: "agent:1:studio:abc", model: "openai/gpt-5", thinkingLevel: "medium", }); expect(client.call).toHaveBeenCalledWith("sessions.patch", { key: "agent:1:studio:abc", model: "openai/gpt-5", thinkingLevel: "medium", }); }); it("patches only model when thinking is omitted", async () => { const client = { call: vi.fn(async () => ({ ok: true })), } as unknown as GatewayClient; await syncGatewaySessionSettings({ client, sessionKey: "agent:1:studio:abc", model: null, }); expect(client.call).toHaveBeenCalledWith("sessions.patch", { key: "agent:1:studio:abc", model: null, }); }); it("patches exec session overrides without model settings", async () => { const client = { call: vi.fn(async () => ({ ok: true })), } as unknown as GatewayClient; await syncGatewaySessionSettings({ client, sessionKey: "agent:1:studio:abc", execHost: "gateway", execSecurity: "allowlist", execAsk: "always", }); expect(client.call).toHaveBeenCalledWith("sessions.patch", { key: "agent:1:studio:abc", execHost: "gateway", execSecurity: "allowlist", execAsk: "always", }); }); });