import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test" import { Hono } from "hono" import type { AnthropicMessagesPayload } from "../src/routes/messages/anthropic-types" import { compactSummaryPromptStart, compactTextOnlyGuard, } from "../src/lib/compact" const actualStateModule = await import("../src/lib/state") const actualConfigModule = await import("../src/lib/config") const actualModelsModule = await import("../src/lib/models") const actualRateLimitModule = await import("../src/lib/rate-limit") const actualUtilsModule = await import("../src/lib/utils") const state = { ...actualStateModule.state, manualApprove: false, verbose: false, } let messagesApiEnabled = true let modelMappings: Record = {} type SelectedModel = { id: string supported_endpoints?: Array } type FlowCallOptions = { compactType?: number requestId: string sessionId?: string subagentMarker?: unknown anthropicBetaHeader?: string } let selectedModel: SelectedModel | undefined const findEndpointModel = mock((_: string) => selectedModel) const checkRateLimit = mock(async () => {}) const handleWithMessagesApi = mock( ( _c: unknown, _payload: AnthropicMessagesPayload, _options: FlowCallOptions, ) => Promise.resolve(new Response("messages")), ) const handleWithResponsesApi = mock( ( _c: unknown, _payload: AnthropicMessagesPayload, _options: FlowCallOptions, ) => Promise.resolve(new Response("responses")), ) const handleWithChatCompletions = mock( ( _c: unknown, _payload: AnthropicMessagesPayload, _options: FlowCallOptions, ) => Promise.resolve(new Response("chat")), ) await mock.module("~/lib/state", () => ({ ...actualStateModule, state, })) await mock.module("~/lib/rate-limit", () => ({ ...actualRateLimitModule, checkRateLimit, })) await mock.module("~/lib/config", () => ({ ...actualConfigModule, getSmallModel: () => "small-model", isMessagesApiEnabled: () => messagesApiEnabled, resolveMappedModel: (model: string) => modelMappings[model] ?? model, })) await mock.module("~/lib/models", () => ({ ...actualModelsModule, findEndpointModel, })) await mock.module("~/lib/utils", () => ({ ...actualUtilsModule, })) const { handleCompletion, messagesFlowHandlers } = await import( "../src/routes/messages/handler" ) const defaultMessagesFlowHandlers = { ...messagesFlowHandlers } const createApp = () => { const app = new Hono() app.post("/", handleCompletion) return app } const createPayload = ( overrides: Partial = {}, ): AnthropicMessagesPayload => ({ model: "original-model", max_tokens: 128, messages: [{ role: "user", content: "hello" }], ...overrides, }) beforeEach(() => { state.manualApprove = false state.verbose = false messagesApiEnabled = true modelMappings = {} selectedModel = undefined messagesFlowHandlers.handleWithMessagesApi = handleWithMessagesApi messagesFlowHandlers.handleWithResponsesApi = handleWithResponsesApi messagesFlowHandlers.handleWithChatCompletions = handleWithChatCompletions checkRateLimit.mockClear() findEndpointModel.mockClear() handleWithMessagesApi.mockClear() handleWithResponsesApi.mockClear() handleWithChatCompletions.mockClear() }) afterEach(() => { messagesFlowHandlers.handleWithMessagesApi = defaultMessagesFlowHandlers.handleWithMessagesApi messagesFlowHandlers.handleWithResponsesApi = defaultMessagesFlowHandlers.handleWithResponsesApi messagesFlowHandlers.handleWithChatCompletions = defaultMessagesFlowHandlers.handleWithChatCompletions }) describe("messages handler orchestration", () => { test("removes executeCode and rewrites getDiagnostics before forwarding tools", async () => { selectedModel = { id: "messages-model", supported_endpoints: ["/v1/messages"], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify( createPayload({ tools: [ { name: "mcp__ide__executeCode", description: "Execute code in VS Code", input_schema: { type: "object" }, }, { name: "mcp__ide__getDiagnostics", description: "Old description", input_schema: { type: "object" }, }, { name: "keep_me", description: "Keep me", input_schema: { type: "object" }, }, ], }), ), }) expect(response.status).toBe(200) expect(await response.text()).toBe("messages") const [, forwardedPayload] = handleWithMessagesApi.mock.calls[0] expect(forwardedPayload.tools).toEqual([ { name: "mcp__ide__getDiagnostics", description: "Get language diagnostics from VS Code. Returns errors, warnings, information, and hints for files in the workspace.", input_schema: { type: "object" }, }, { name: "keep_me", description: "Keep me", input_schema: { type: "object" }, }, ]) }) test("adds cache_control to the last content block after merging tool_result content", async () => { selectedModel = { id: "messages-model", supported_endpoints: ["/v1/messages"], } const payload: AnthropicMessagesPayload = { model: "original-model", max_tokens: 128, messages: [ { role: "user", content: [ { type: "tool_result", tool_use_id: "tool-1", content: "Launching skill: foo", }, { type: "text", text: "[Pasted ~4 lines]", }, ], }, ], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(payload), }) expect(response.status).toBe(200) expect(await response.text()).toBe("messages") const [, forwardedPayload] = handleWithMessagesApi.mock.calls[0] expect(forwardedPayload.messages[0]).toEqual({ role: "user", content: [ { type: "tool_result", tool_use_id: "tool-1", content: "Launching skill: foo\n\n[Pasted ~4 lines]", cache_control: { type: "ephemeral", }, }, ], }) }) test("preserves cache_control captured before Tool loaded is stripped", async () => { selectedModel = { id: "messages-model", supported_endpoints: ["/v1/messages"], } const payload: AnthropicMessagesPayload = { model: "original-model", max_tokens: 128, messages: [ { role: "user", content: [ { type: "tool_result", tool_use_id: "tool-1", content: [ { type: "tool_reference", tool_name: "AskUserQuestion", }, ], }, { type: "text", text: "Tool loaded.", cache_control: { type: "ephemeral", scope: "user", }, }, ], }, ], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(payload), }) expect(response.status).toBe(200) expect(await response.text()).toBe("messages") const [, forwardedPayload] = handleWithMessagesApi.mock.calls[0] expect(forwardedPayload.messages[0]).toEqual({ role: "user", content: [ { type: "tool_result", tool_use_id: "tool-1", content: [ { type: "tool_reference", tool_name: "AskUserQuestion", }, ], cache_control: { type: "ephemeral", scope: "user", }, }, ], }) }) test("delegates to the Messages API flow when the model supports /v1/messages", async () => { selectedModel = { id: "messages-model", supported_endpoints: ["/v1/messages"], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(createPayload()), }) expect(response.status).toBe(200) expect(await response.text()).toBe("messages") expect(handleWithMessagesApi).toHaveBeenCalledTimes(1) expect(handleWithResponsesApi).not.toHaveBeenCalled() expect(handleWithChatCompletions).not.toHaveBeenCalled() const [, forwardedPayload] = handleWithMessagesApi.mock.calls[0] expect(forwardedPayload.model).toBe("messages-model") }) test("maps the requested model before resolving the endpoint model", async () => { modelMappings = { "claude-opus-4-7": "messages-model", } selectedModel = { id: "messages-model", supported_endpoints: ["/v1/messages"], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(createPayload({ model: "claude-opus-4-7" })), }) expect(response.status).toBe(200) expect(await response.text()).toBe("messages") expect(findEndpointModel).toHaveBeenCalledWith("messages-model") const [, forwardedPayload] = handleWithMessagesApi.mock.calls[0] expect(forwardedPayload.model).toBe("messages-model") }) test("delegates to the Responses API flow when the model supports /responses", async () => { selectedModel = { id: "responses-model", supported_endpoints: ["/responses"], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(createPayload()), }) expect(response.status).toBe(200) expect(await response.text()).toBe("responses") expect(handleWithMessagesApi).not.toHaveBeenCalled() expect(handleWithResponsesApi).toHaveBeenCalledTimes(1) expect(handleWithChatCompletions).not.toHaveBeenCalled() }) test("delegates to the Responses API flow when the model supports ws:/responses", async () => { selectedModel = { id: "responses-ws-model", supported_endpoints: ["ws:/responses"], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(createPayload()), }) expect(response.status).toBe(200) expect(await response.text()).toBe("responses") expect(handleWithMessagesApi).not.toHaveBeenCalled() expect(handleWithResponsesApi).toHaveBeenCalledTimes(1) expect(handleWithChatCompletions).not.toHaveBeenCalled() }) test("does not delegate compact requests to a ws-only Responses API model", async () => { selectedModel = { id: "responses-ws-model", supported_endpoints: ["ws:/responses"], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify( createPayload({ messages: [ { role: "user", content: `${compactTextOnlyGuard}\n\n${compactSummaryPromptStart}\n\nPending Tasks:\n- one\n\nCurrent Work:\n- two`, }, ], }), ), }) expect(response.status).toBe(200) expect(await response.text()).toBe("chat") expect(handleWithMessagesApi).not.toHaveBeenCalled() expect(handleWithResponsesApi).not.toHaveBeenCalled() expect(handleWithChatCompletions).toHaveBeenCalledTimes(1) }) test("falls back to the Chat Completions flow when no endpoint matches", async () => { selectedModel = { id: "chat-model", supported_endpoints: [], } const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(createPayload()), }) expect(response.status).toBe(200) expect(await response.text()).toBe("chat") expect(handleWithMessagesApi).not.toHaveBeenCalled() expect(handleWithResponsesApi).not.toHaveBeenCalled() expect(handleWithChatCompletions).toHaveBeenCalledTimes(1) }) test("applies warmup model override and passes request metadata to the selected flow", async () => { selectedModel = { id: "messages-model", supported_endpoints: ["/v1/messages"], } const payload = createPayload({ messages: [ { role: "user", content: [ { type: "text", text: '__SUBAGENT_MARKER__{"session_id":"sub-session","agent_id":"agent-1","agent_type":"Explore"}', }, { type: "text", text: "hello", }, ], }, ], }) const app = createApp() const response = await app.request("/", { method: "POST", headers: { "content-type": "application/json", "anthropic-beta": "warmup-beta", "x-session-id": "session-123", }, body: JSON.stringify(payload), }) expect(response.status).toBe(200) expect(await response.text()).toBe("messages") expect(findEndpointModel).toHaveBeenCalledWith("small-model") const expectedSessionId = actualUtilsModule.getUUID("session-123") const expectedRequestId = actualUtilsModule.generateRequestIdFromPayload( payload, expectedSessionId, ) const options = handleWithMessagesApi.mock.calls[0][2] expect(options.requestId).toBe(expectedRequestId) expect(options.sessionId).toBe(expectedSessionId) expect(options.subagentMarker).toEqual({ session_id: "sub-session", agent_id: "agent-1", agent_type: "Explore", }) expect(options.anthropicBetaHeader).toBe("warmup-beta") }) })