import { describe, expect, it } from "bun:test" import { createAnthropicEffortHook } from "./index" interface ChatParamsInput { sessionID: string agent: { name?: string } model: { providerID: string; modelID: string; id?: string; api?: { npm?: string } } provider: { id: string } message: { variant?: string } } interface ChatParamsOutput { temperature?: number topP?: number topK?: number options: Record } function createMockParams(overrides: { providerID?: string modelID?: string variant?: string agentName?: string existingOptions?: Record }): { input: ChatParamsInput; output: ChatParamsOutput } { const providerID = overrides.providerID ?? "anthropic" const modelID = overrides.modelID ?? "claude-opus-4-6" const variant = "variant" in overrides ? overrides.variant : "max" const agentName = overrides.agentName ?? "sisyphus" const existingOptions = overrides.existingOptions ?? {} return { input: { sessionID: "test-session", agent: { name: agentName }, model: { providerID, modelID }, provider: { id: providerID }, message: { variant }, }, output: { temperature: 0.1, options: { ...existingOptions }, }, } } describe("createAnthropicEffortHook", () => { describe("opus 4-6 with variant max", () => { it("should inject effort max for anthropic opus-4-6 with variant max", async () => { //#given anthropic opus-4-6 model with variant max const hook = createAnthropicEffortHook() const { input, output } = createMockParams({}) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should be injected into options expect(output.options.effort).toBe("max") }) it("should inject effort max for github-copilot claude-opus-4-6", async () => { //#given github-copilot provider with claude-opus-4-6 const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ providerID: "github-copilot", modelID: "claude-opus-4-6", }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should be injected (github-copilot resolves to anthropic) expect(output.options.effort).toBe("max") }) it("should inject effort max for opencode provider with claude-opus-4-6", async () => { //#given opencode provider with claude-opus-4-6 const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ providerID: "opencode", modelID: "claude-opus-4-6", }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should be injected expect(output.options.effort).toBe("max") }) it("should inject effort max for google-vertex-anthropic provider", async () => { //#given google-vertex-anthropic provider with claude-opus-4-6 const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ providerID: "google-vertex-anthropic", modelID: "claude-opus-4-6", }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should be injected expect(output.options.effort).toBe("max") }) it("should handle normalized model ID with dots (opus-4.6)", async () => { //#given model ID with dots instead of hyphens const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ modelID: "claude-opus-4.6", }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then should normalize and inject effort expect(output.options.effort).toBe("max") }) }) describe("conditions NOT met - should skip", () => { it("should NOT inject effort when variant is not max", async () => { //#given opus-4-6 with variant high (not max) const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ variant: "high" }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should NOT be injected expect(output.options.effort).toBeUndefined() }) it("should NOT inject effort when variant is undefined", async () => { //#given opus-4-6 with no variant const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ variant: undefined }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should NOT be injected expect(output.options.effort).toBeUndefined() }) it("should NOT inject effort for non-opus model", async () => { //#given claude-sonnet-4-6 (not opus) const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ modelID: "claude-sonnet-4-6", }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should NOT be injected expect(output.options.effort).toBeUndefined() }) it("should NOT inject effort for non-anthropic provider with non-claude model", async () => { //#given openai provider with gpt model const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ providerID: "openai", modelID: "gpt-5.2", }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should NOT be injected expect(output.options.effort).toBeUndefined() }) it("should NOT throw when model.modelID is undefined", async () => { //#given model with undefined modelID (runtime edge case) const hook = createAnthropicEffortHook() const input = { sessionID: "test-session", agent: { name: "sisyphus" }, model: { providerID: "anthropic", modelID: undefined as unknown as string }, provider: { id: "anthropic" }, message: { variant: "max" as const }, } const output = { temperature: 0.1, options: {} } //#when chat.params hook is called with undefined modelID await hook["chat.params"](input, output) //#then should gracefully skip without throwing expect(output.options.effort).toBeUndefined() }) }) describe("preserves existing options", () => { it("should NOT overwrite existing effort if already set", async () => { //#given options already have effort set const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ existingOptions: { effort: "high" }, }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then existing effort should be preserved expect(output.options.effort).toBe("high") }) it("should preserve other existing options when injecting effort", async () => { //#given options with existing thinking config const hook = createAnthropicEffortHook() const { input, output } = createMockParams({ existingOptions: { thinking: { type: "enabled", budgetTokens: 31999 }, }, }) //#when chat.params hook is called await hook["chat.params"](input, output) //#then effort should be added without affecting thinking expect(output.options.effort).toBe("max") expect(output.options.thinking).toEqual({ type: "enabled", budgetTokens: 31999, }) }) }) })