Spaces:
Configuration error
Configuration error
| import { describe, expect, it, vi } from "vitest"; | |
| import type { GatewayRequestContext } from "./types.js"; | |
| import { agentHandlers } from "./agent.js"; | |
| const mocks = vi.hoisted(() => ({ | |
| loadSessionEntry: vi.fn(), | |
| updateSessionStore: vi.fn(), | |
| agentCommand: vi.fn(), | |
| registerAgentRunContext: vi.fn(), | |
| })); | |
| vi.mock("../session-utils.js", () => ({ | |
| loadSessionEntry: mocks.loadSessionEntry, | |
| })); | |
| vi.mock("../../config/sessions.js", async () => { | |
| const actual = await vi.importActual<typeof import("../../config/sessions.js")>( | |
| "../../config/sessions.js", | |
| ); | |
| return { | |
| ...actual, | |
| updateSessionStore: mocks.updateSessionStore, | |
| resolveAgentIdFromSessionKey: () => "main", | |
| resolveExplicitAgentSessionKey: () => undefined, | |
| resolveAgentMainSessionKey: () => "agent:main:main", | |
| }; | |
| }); | |
| vi.mock("../../commands/agent.js", () => ({ | |
| agentCommand: mocks.agentCommand, | |
| })); | |
| vi.mock("../../config/config.js", () => ({ | |
| loadConfig: () => ({}), | |
| })); | |
| vi.mock("../../agents/agent-scope.js", () => ({ | |
| listAgentIds: () => ["main"], | |
| })); | |
| vi.mock("../../infra/agent-events.js", () => ({ | |
| registerAgentRunContext: mocks.registerAgentRunContext, | |
| onAgentEvent: vi.fn(), | |
| })); | |
| vi.mock("../../sessions/send-policy.js", () => ({ | |
| resolveSendPolicy: () => "allow", | |
| })); | |
| vi.mock("../../utils/delivery-context.js", async () => { | |
| const actual = await vi.importActual<typeof import("../../utils/delivery-context.js")>( | |
| "../../utils/delivery-context.js", | |
| ); | |
| return { | |
| ...actual, | |
| normalizeSessionDeliveryFields: () => ({}), | |
| }; | |
| }); | |
| const makeContext = (): GatewayRequestContext => | |
| ({ | |
| dedupe: new Map(), | |
| addChatRun: vi.fn(), | |
| logGateway: { info: vi.fn(), error: vi.fn() }, | |
| }) as unknown as GatewayRequestContext; | |
| describe("gateway agent handler", () => { | |
| it("preserves cliSessionIds from existing session entry", async () => { | |
| const existingCliSessionIds = { "claude-cli": "abc-123-def" }; | |
| const existingClaudeCliSessionId = "abc-123-def"; | |
| mocks.loadSessionEntry.mockReturnValue({ | |
| cfg: {}, | |
| storePath: "/tmp/sessions.json", | |
| entry: { | |
| sessionId: "existing-session-id", | |
| updatedAt: Date.now(), | |
| cliSessionIds: existingCliSessionIds, | |
| claudeCliSessionId: existingClaudeCliSessionId, | |
| }, | |
| canonicalKey: "agent:main:main", | |
| }); | |
| let capturedEntry: Record<string, unknown> | undefined; | |
| mocks.updateSessionStore.mockImplementation(async (_path, updater) => { | |
| const store: Record<string, unknown> = {}; | |
| await updater(store); | |
| capturedEntry = store["agent:main:main"] as Record<string, unknown>; | |
| }); | |
| mocks.agentCommand.mockResolvedValue({ | |
| payloads: [{ text: "ok" }], | |
| meta: { durationMs: 100 }, | |
| }); | |
| const respond = vi.fn(); | |
| await agentHandlers.agent({ | |
| params: { | |
| message: "test", | |
| agentId: "main", | |
| sessionKey: "agent:main:main", | |
| idempotencyKey: "test-idem", | |
| }, | |
| respond, | |
| context: makeContext(), | |
| req: { type: "req", id: "1", method: "agent" }, | |
| client: null, | |
| isWebchatConnect: () => false, | |
| }); | |
| expect(mocks.updateSessionStore).toHaveBeenCalled(); | |
| expect(capturedEntry).toBeDefined(); | |
| expect(capturedEntry?.cliSessionIds).toEqual(existingCliSessionIds); | |
| expect(capturedEntry?.claudeCliSessionId).toBe(existingClaudeCliSessionId); | |
| }); | |
| it("handles missing cliSessionIds gracefully", async () => { | |
| mocks.loadSessionEntry.mockReturnValue({ | |
| cfg: {}, | |
| storePath: "/tmp/sessions.json", | |
| entry: { | |
| sessionId: "existing-session-id", | |
| updatedAt: Date.now(), | |
| // No cliSessionIds or claudeCliSessionId | |
| }, | |
| canonicalKey: "agent:main:main", | |
| }); | |
| let capturedEntry: Record<string, unknown> | undefined; | |
| mocks.updateSessionStore.mockImplementation(async (_path, updater) => { | |
| const store: Record<string, unknown> = {}; | |
| await updater(store); | |
| capturedEntry = store["agent:main:main"] as Record<string, unknown>; | |
| }); | |
| mocks.agentCommand.mockResolvedValue({ | |
| payloads: [{ text: "ok" }], | |
| meta: { durationMs: 100 }, | |
| }); | |
| const respond = vi.fn(); | |
| await agentHandlers.agent({ | |
| params: { | |
| message: "test", | |
| agentId: "main", | |
| sessionKey: "agent:main:main", | |
| idempotencyKey: "test-idem-2", | |
| }, | |
| respond, | |
| context: makeContext(), | |
| req: { type: "req", id: "2", method: "agent" }, | |
| client: null, | |
| isWebchatConnect: () => false, | |
| }); | |
| expect(mocks.updateSessionStore).toHaveBeenCalled(); | |
| expect(capturedEntry).toBeDefined(); | |
| // Should be undefined, not cause an error | |
| expect(capturedEntry?.cliSessionIds).toBeUndefined(); | |
| expect(capturedEntry?.claudeCliSessionId).toBeUndefined(); | |
| }); | |
| }); | |