refactor: major codebase cleanup - BDD comments, file splitting, bug fixes (#1350)

* style(tests): normalize BDD comments from '// #given' to '// given'

- Replace 4,668 Python-style BDD comments across 107 test files
- Patterns changed: // #given -> // given, // #when -> // when, // #then -> // then
- Also handles no-space variants: //#given -> // given

* fix(rules-injector): prefer output.metadata.filePath over output.title

- Extract file path resolution to dedicated output-path.ts module
- Prefer metadata.filePath which contains actual file path
- Fall back to output.title only when metadata unavailable
- Fixes issue where rules weren't injected when tool output title was a label

* feat(slashcommand): add optional user_message parameter

- Add user_message optional parameter for command arguments
- Model can now call: command='publish' user_message='patch'
- Improves error messages with clearer format guidance
- Helps LLMs understand correct parameter usage

* feat(hooks): restore compaction-context-injector hook

- Restore hook deleted in cbbc7bd0 for session compaction context
- Injects 7 mandatory sections: User Requests, Final Goal, Work Completed,
  Remaining Tasks, Active Working Context, MUST NOT Do, Agent Verification State
- Re-register in hooks/index.ts and main plugin entry

* refactor(background-agent): split manager.ts into focused modules

- Extract constants.ts for TTL values and internal types (52 lines)
- Extract state.ts for TaskStateManager class (204 lines)
- Extract spawner.ts for task creation logic (244 lines)
- Extract result-handler.ts for completion handling (265 lines)
- Reduce manager.ts from 1377 to 755 lines (45% reduction)
- Maintain backward compatible exports

* refactor(agents): split prometheus-prompt.ts into subdirectory

- Move 1196-line prometheus-prompt.ts to prometheus/ subdirectory
- Organize prompt sections into separate files for maintainability
- Update agents/index.ts exports

* refactor(delegate-task): split tools.ts into focused modules

- Extract categories.ts for category definitions and routing
- Extract executor.ts for task execution logic
- Extract helpers.ts for utility functions
- Extract prompt-builder.ts for prompt construction
- Reduce tools.ts complexity with cleaner separation of concerns

* refactor(builtin-skills): split skills.ts into individual skill files

- Move each skill to dedicated file in skills/ subdirectory
- Create barrel export for backward compatibility
- Improve maintainability with focused skill modules

* chore: update import paths and lockfile

- Update prometheus import path after refactor
- Update bun.lock

* fix(tests): complete BDD comment normalization

- Fix remaining #when/#then patterns missed by initial sed
- Affected: state.test.ts, events.test.ts

---------

Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
This commit is contained in:
YeonGyu-Kim
2026-02-01 16:47:50 +09:00
committed by GitHub
parent c83150d9ea
commit f146aeff0f
145 changed files with 10307 additions and 9562 deletions
+60 -60
View File
@@ -37,7 +37,7 @@ describe("createThinkModeHook integration", () => {
describe("GitHub Copilot provider integration", () => {
describe("Claude models", () => {
it("should activate thinking mode for github-copilot Claude with think keyword", async () => {
// #given a github-copilot Claude model and prompt with "think" keyword
// given a github-copilot Claude model and prompt with "think" keyword
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -45,10 +45,10 @@ describe("createThinkModeHook integration", () => {
"Please think deeply about this problem"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant and inject thinking config
// then should upgrade to high variant and inject thinking config
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("claude-opus-4-5-high")
expect(message.thinking).toBeDefined()
@@ -61,7 +61,7 @@ describe("createThinkModeHook integration", () => {
})
it("should handle github-copilot Claude with dots in version", async () => {
// #given a github-copilot Claude model with dot format (claude-opus-4.5)
// given a github-copilot Claude model with dot format (claude-opus-4.5)
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -69,17 +69,17 @@ describe("createThinkModeHook integration", () => {
"ultrathink mode"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant (hyphen format)
// then should upgrade to high variant (hyphen format)
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("claude-opus-4-5-high")
expect(message.thinking).toBeDefined()
})
it("should handle github-copilot Claude Sonnet", async () => {
// #given a github-copilot Claude Sonnet model
// given a github-copilot Claude Sonnet model
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -87,10 +87,10 @@ describe("createThinkModeHook integration", () => {
"think about this"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant
// then should upgrade to high variant
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("claude-sonnet-4-5-high")
expect(message.thinking).toBeDefined()
@@ -99,7 +99,7 @@ describe("createThinkModeHook integration", () => {
describe("Gemini models", () => {
it("should activate thinking mode for github-copilot Gemini Pro", async () => {
// #given a github-copilot Gemini Pro model
// given a github-copilot Gemini Pro model
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -107,10 +107,10 @@ describe("createThinkModeHook integration", () => {
"think about this"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant and inject google thinking config
// then should upgrade to high variant and inject google thinking config
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gemini-3-pro-high")
expect(message.providerOptions).toBeDefined()
@@ -121,7 +121,7 @@ describe("createThinkModeHook integration", () => {
})
it("should activate thinking mode for github-copilot Gemini Flash", async () => {
// #given a github-copilot Gemini Flash model
// given a github-copilot Gemini Flash model
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -129,10 +129,10 @@ describe("createThinkModeHook integration", () => {
"ultrathink"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant
// then should upgrade to high variant
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gemini-3-flash-high")
expect(message.providerOptions).toBeDefined()
@@ -141,7 +141,7 @@ describe("createThinkModeHook integration", () => {
describe("GPT models", () => {
it("should activate thinking mode for github-copilot GPT-5.2", async () => {
// #given a github-copilot GPT-5.2 model
// given a github-copilot GPT-5.2 model
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -149,24 +149,24 @@ describe("createThinkModeHook integration", () => {
"please think"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant and inject openai thinking config
// then should upgrade to high variant and inject openai thinking config
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gpt-5-2-high")
expect(message.reasoning_effort).toBe("high")
})
it("should activate thinking mode for github-copilot GPT-5", async () => {
// #given a github-copilot GPT-5 model
// given a github-copilot GPT-5 model
const hook = createThinkModeHook()
const input = createMockInput("github-copilot", "gpt-5", "think deeply")
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should upgrade to high variant
// then should upgrade to high variant
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gpt-5-high")
expect(message.reasoning_effort).toBe("high")
@@ -175,7 +175,7 @@ describe("createThinkModeHook integration", () => {
describe("No think keyword", () => {
it("should NOT activate for github-copilot without think keyword", async () => {
// #given a prompt without any think keyword
// given a prompt without any think keyword
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -184,10 +184,10 @@ describe("createThinkModeHook integration", () => {
)
const originalModelID = input.message.model?.modelID
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should NOT change model or inject config
// then should NOT change model or inject config
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe(originalModelID)
expect(message.thinking).toBeUndefined()
@@ -197,7 +197,7 @@ describe("createThinkModeHook integration", () => {
describe("Backwards compatibility with direct providers", () => {
it("should still work for direct anthropic provider", async () => {
// #given direct anthropic provider
// given direct anthropic provider
const hook = createThinkModeHook()
const input = createMockInput(
"anthropic",
@@ -205,17 +205,17 @@ describe("createThinkModeHook integration", () => {
"think about this"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should work as before
// then should work as before
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("claude-sonnet-4-5-high")
expect(message.thinking).toBeDefined()
})
it("should still work for direct google provider", async () => {
// #given direct google provider
// given direct google provider
const hook = createThinkModeHook()
const input = createMockInput(
"google",
@@ -223,31 +223,31 @@ describe("createThinkModeHook integration", () => {
"think about this"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should work as before
// then should work as before
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gemini-3-pro-high")
expect(message.providerOptions).toBeDefined()
})
it("should still work for direct openai provider", async () => {
// #given direct openai provider
// given direct openai provider
const hook = createThinkModeHook()
const input = createMockInput("openai", "gpt-5", "think about this")
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should work
// then should work
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gpt-5-high")
expect(message.reasoning_effort).toBe("high")
})
it("should still work for amazon-bedrock provider", async () => {
// #given amazon-bedrock provider
// given amazon-bedrock provider
const hook = createThinkModeHook()
const input = createMockInput(
"amazon-bedrock",
@@ -255,10 +255,10 @@ describe("createThinkModeHook integration", () => {
"think"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should inject bedrock thinking config
// then should inject bedrock thinking config
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("claude-sonnet-4-5-high")
expect(message.reasoningConfig).toBeDefined()
@@ -267,7 +267,7 @@ describe("createThinkModeHook integration", () => {
describe("Already-high variants", () => {
it("should NOT re-upgrade already-high variants", async () => {
// #given an already-high variant model
// given an already-high variant model
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -275,10 +275,10 @@ describe("createThinkModeHook integration", () => {
"think deeply"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should NOT modify the model (already high)
// then should NOT modify the model (already high)
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("claude-opus-4-5-high")
// No additional thinking config should be injected
@@ -286,7 +286,7 @@ describe("createThinkModeHook integration", () => {
})
it("should NOT re-upgrade already-high GPT variants", async () => {
// #given an already-high GPT variant
// given an already-high GPT variant
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -294,10 +294,10 @@ describe("createThinkModeHook integration", () => {
"ultrathink"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should NOT modify the model
// then should NOT modify the model
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("gpt-5.2-high")
expect(message.reasoning_effort).toBeUndefined()
@@ -306,7 +306,7 @@ describe("createThinkModeHook integration", () => {
describe("Unknown models", () => {
it("should not crash for unknown models via github-copilot", async () => {
// #given an unknown model type
// given an unknown model type
const hook = createThinkModeHook()
const input = createMockInput(
"github-copilot",
@@ -314,46 +314,46 @@ describe("createThinkModeHook integration", () => {
"think about this"
)
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should not crash and model should remain unchanged
// then should not crash and model should remain unchanged
expect(input.message.model?.modelID).toBe("llama-3-70b")
})
})
describe("Edge cases", () => {
it("should handle missing model gracefully", async () => {
// #given input without a model
// given input without a model
const hook = createThinkModeHook()
const input: ThinkModeInput = {
parts: [{ type: "text", text: "think about this" }],
message: {},
}
// #when the chat.params hook is called
// #then should not crash
// when the chat.params hook is called
// then should not crash
await expect(
hook["chat.params"](input, sessionID)
).resolves.toBeUndefined()
})
it("should handle empty prompt gracefully", async () => {
// #given empty prompt
// given empty prompt
const hook = createThinkModeHook()
const input = createMockInput("github-copilot", "claude-opus-4-5", "")
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should not upgrade (no think keyword)
// then should not upgrade (no think keyword)
expect(input.message.model?.modelID).toBe("claude-opus-4-5")
})
})
describe("Agent-level thinking configuration respect", () => {
it("should NOT inject thinking config when agent has thinking disabled", async () => {
// #given agent with thinking explicitly disabled
// given agent with thinking explicitly disabled
const hook = createThinkModeHook()
const input: ThinkModeInput = {
parts: [{ type: "text", text: "ultrathink deeply" }],
@@ -363,17 +363,17 @@ describe("createThinkModeHook integration", () => {
} as ThinkModeInput["message"],
}
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should NOT override agent's thinking disabled setting
// then should NOT override agent's thinking disabled setting
const message = input.message as MessageWithInjectedProps
expect((message.thinking as { type: string }).type).toBe("disabled")
expect(message.providerOptions).toBeUndefined()
})
it("should NOT inject thinking config when agent has custom providerOptions", async () => {
// #given agent with custom providerOptions
// given agent with custom providerOptions
const hook = createThinkModeHook()
const input: ThinkModeInput = {
parts: [{ type: "text", text: "ultrathink" }],
@@ -385,10 +385,10 @@ describe("createThinkModeHook integration", () => {
} as ThinkModeInput["message"],
}
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should NOT override agent's providerOptions
// then should NOT override agent's providerOptions
const message = input.message as MessageWithInjectedProps
const providerOpts = message.providerOptions as Record<string, unknown>
expect((providerOpts.google as Record<string, unknown>).thinkingConfig).toEqual({
@@ -397,14 +397,14 @@ describe("createThinkModeHook integration", () => {
})
it("should still inject thinking config when agent has no thinking override", async () => {
// #given agent without thinking override
// given agent without thinking override
const hook = createThinkModeHook()
const input = createMockInput("google", "gemini-3-pro", "ultrathink")
// #when the chat.params hook is called
// when the chat.params hook is called
await hook["chat.params"](input, sessionID)
// #then should inject thinking config as normal
// then should inject thinking config as normal
const message = input.message as MessageWithInjectedProps
expect(message.providerOptions).toBeDefined()
})
+84 -84
View File
@@ -10,14 +10,14 @@ describe("think-mode switcher", () => {
describe("GitHub Copilot provider support", () => {
describe("Claude models via github-copilot", () => {
it("should resolve github-copilot Claude Opus to anthropic config", () => {
// #given a github-copilot provider with Claude Opus model
// given a github-copilot provider with Claude Opus model
const providerID = "github-copilot"
const modelID = "claude-opus-4-5"
// #when getting thinking config
// when getting thinking config
const config = getThinkingConfig(providerID, modelID)
// #then should return anthropic thinking config
// then should return anthropic thinking config
expect(config).not.toBeNull()
expect(config?.thinking).toBeDefined()
expect((config?.thinking as Record<string, unknown>)?.type).toBe(
@@ -29,19 +29,19 @@ describe("think-mode switcher", () => {
})
it("should resolve github-copilot Claude Sonnet to anthropic config", () => {
// #given a github-copilot provider with Claude Sonnet model
// given a github-copilot provider with Claude Sonnet model
const config = getThinkingConfig("github-copilot", "claude-sonnet-4-5")
// #then should return anthropic thinking config
// then should return anthropic thinking config
expect(config).not.toBeNull()
expect(config?.thinking).toBeDefined()
})
it("should handle Claude with dots in version number", () => {
// #given a model ID with dots (claude-opus-4.5)
// given a model ID with dots (claude-opus-4.5)
const config = getThinkingConfig("github-copilot", "claude-opus-4.5")
// #then should still return anthropic thinking config
// then should still return anthropic thinking config
expect(config).not.toBeNull()
expect(config?.thinking).toBeDefined()
})
@@ -49,10 +49,10 @@ describe("think-mode switcher", () => {
describe("Gemini models via github-copilot", () => {
it("should resolve github-copilot Gemini Pro to google config", () => {
// #given a github-copilot provider with Gemini Pro model
// given a github-copilot provider with Gemini Pro model
const config = getThinkingConfig("github-copilot", "gemini-3-pro")
// #then should return google thinking config
// then should return google thinking config
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
const googleOptions = (
@@ -62,13 +62,13 @@ describe("think-mode switcher", () => {
})
it("should resolve github-copilot Gemini Flash to google config", () => {
// #given a github-copilot provider with Gemini Flash model
// given a github-copilot provider with Gemini Flash model
const config = getThinkingConfig(
"github-copilot",
"gemini-3-flash"
)
// #then should return google thinking config
// then should return google thinking config
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
})
@@ -76,37 +76,37 @@ describe("think-mode switcher", () => {
describe("GPT models via github-copilot", () => {
it("should resolve github-copilot GPT-5.2 to openai config", () => {
// #given a github-copilot provider with GPT-5.2 model
// given a github-copilot provider with GPT-5.2 model
const config = getThinkingConfig("github-copilot", "gpt-5.2")
// #then should return openai thinking config
// then should return openai thinking config
expect(config).not.toBeNull()
expect(config?.reasoning_effort).toBe("high")
})
it("should resolve github-copilot GPT-5 to openai config", () => {
// #given a github-copilot provider with GPT-5 model
// given a github-copilot provider with GPT-5 model
const config = getThinkingConfig("github-copilot", "gpt-5")
// #then should return openai thinking config
// then should return openai thinking config
expect(config).not.toBeNull()
expect(config?.reasoning_effort).toBe("high")
})
it("should resolve github-copilot o1 to openai config", () => {
// #given a github-copilot provider with o1 model
// given a github-copilot provider with o1 model
const config = getThinkingConfig("github-copilot", "o1-preview")
// #then should return openai thinking config
// then should return openai thinking config
expect(config).not.toBeNull()
expect(config?.reasoning_effort).toBe("high")
})
it("should resolve github-copilot o3 to openai config", () => {
// #given a github-copilot provider with o3 model
// given a github-copilot provider with o3 model
const config = getThinkingConfig("github-copilot", "o3-mini")
// #then should return openai thinking config
// then should return openai thinking config
expect(config).not.toBeNull()
expect(config?.reasoning_effort).toBe("high")
})
@@ -114,10 +114,10 @@ describe("think-mode switcher", () => {
describe("Unknown models via github-copilot", () => {
it("should return null for unknown model types", () => {
// #given a github-copilot provider with unknown model
// given a github-copilot provider with unknown model
const config = getThinkingConfig("github-copilot", "llama-3-70b")
// #then should return null (no matching provider)
// then should return null (no matching provider)
expect(config).toBeNull()
})
})
@@ -126,39 +126,39 @@ describe("think-mode switcher", () => {
describe("Model ID normalization", () => {
describe("getHighVariant with dots vs hyphens", () => {
it("should handle dots in Claude version numbers", () => {
// #given a Claude model ID with dot format
// given a Claude model ID with dot format
const variant = getHighVariant("claude-opus-4.5")
// #then should return high variant with hyphen format
// then should return high variant with hyphen format
expect(variant).toBe("claude-opus-4-5-high")
})
it("should handle hyphens in Claude version numbers", () => {
// #given a Claude model ID with hyphen format
// given a Claude model ID with hyphen format
const variant = getHighVariant("claude-opus-4-5")
// #then should return high variant
// then should return high variant
expect(variant).toBe("claude-opus-4-5-high")
})
it("should handle dots in GPT version numbers", () => {
// #given a GPT model ID with dot format (gpt-5.2)
// given a GPT model ID with dot format (gpt-5.2)
const variant = getHighVariant("gpt-5.2")
// #then should return high variant
// then should return high variant
expect(variant).toBe("gpt-5-2-high")
})
it("should handle dots in GPT-5.1 codex variants", () => {
// #given a GPT-5.1-codex model ID
// given a GPT-5.1-codex model ID
const variant = getHighVariant("gpt-5.1-codex")
// #then should return high variant
// then should return high variant
expect(variant).toBe("gpt-5-1-codex-high")
})
it("should handle Gemini preview variants", () => {
// #given Gemini preview model IDs
// given Gemini preview model IDs
expect(getHighVariant("gemini-3-pro")).toBe(
"gemini-3-pro-high"
)
@@ -168,14 +168,14 @@ describe("think-mode switcher", () => {
})
it("should return null for already-high variants", () => {
// #given model IDs that are already high variants
// given model IDs that are already high variants
expect(getHighVariant("claude-opus-4-5-high")).toBeNull()
expect(getHighVariant("gpt-5-2-high")).toBeNull()
expect(getHighVariant("gemini-3-pro-high")).toBeNull()
})
it("should return null for unknown models", () => {
// #given unknown model IDs
// given unknown model IDs
expect(getHighVariant("llama-3-70b")).toBeNull()
expect(getHighVariant("mistral-large")).toBeNull()
})
@@ -184,19 +184,19 @@ describe("think-mode switcher", () => {
describe("isAlreadyHighVariant", () => {
it("should detect -high suffix", () => {
// #given model IDs with -high suffix
// given model IDs with -high suffix
expect(isAlreadyHighVariant("claude-opus-4-5-high")).toBe(true)
expect(isAlreadyHighVariant("gpt-5-2-high")).toBe(true)
expect(isAlreadyHighVariant("gemini-3-pro-high")).toBe(true)
})
it("should detect -high suffix after normalization", () => {
// #given model IDs with dots that end in -high
// given model IDs with dots that end in -high
expect(isAlreadyHighVariant("gpt-5.2-high")).toBe(true)
})
it("should return false for base models", () => {
// #given base model IDs without -high suffix
// given base model IDs without -high suffix
expect(isAlreadyHighVariant("claude-opus-4-5")).toBe(false)
expect(isAlreadyHighVariant("claude-opus-4.5")).toBe(false)
expect(isAlreadyHighVariant("gpt-5.2")).toBe(false)
@@ -204,7 +204,7 @@ describe("think-mode switcher", () => {
})
it("should return false for models with 'high' in name but not suffix", () => {
// #given model IDs that contain 'high' but not as suffix
// given model IDs that contain 'high' but not as suffix
expect(isAlreadyHighVariant("high-performance-model")).toBe(false)
})
})
@@ -212,7 +212,7 @@ describe("think-mode switcher", () => {
describe("getThinkingConfig", () => {
describe("Already high variants", () => {
it("should return null for already-high variants", () => {
// #given already-high model variants
// given already-high model variants
expect(
getThinkingConfig("anthropic", "claude-opus-4-5-high")
).toBeNull()
@@ -221,7 +221,7 @@ describe("think-mode switcher", () => {
})
it("should return null for already-high variants via github-copilot", () => {
// #given already-high model variants via github-copilot
// given already-high model variants via github-copilot
expect(
getThinkingConfig("github-copilot", "claude-opus-4-5-high")
).toBeNull()
@@ -231,7 +231,7 @@ describe("think-mode switcher", () => {
describe("Non-thinking-capable models", () => {
it("should return null for non-thinking-capable models", () => {
// #given models that don't support thinking mode
// given models that don't support thinking mode
expect(getThinkingConfig("anthropic", "claude-2")).toBeNull()
expect(getThinkingConfig("openai", "gpt-4")).toBeNull()
expect(getThinkingConfig("google", "gemini-1")).toBeNull()
@@ -240,7 +240,7 @@ describe("think-mode switcher", () => {
describe("Unknown providers", () => {
it("should return null for unknown providers", () => {
// #given unknown provider IDs
// given unknown provider IDs
expect(getThinkingConfig("unknown-provider", "some-model")).toBeNull()
expect(getThinkingConfig("azure", "gpt-5")).toBeNull()
})
@@ -249,38 +249,38 @@ describe("think-mode switcher", () => {
describe("Direct provider configs (backwards compatibility)", () => {
it("should still work for direct anthropic provider", () => {
// #given direct anthropic provider
// given direct anthropic provider
const config = getThinkingConfig("anthropic", "claude-opus-4-5")
// #then should return anthropic thinking config
// then should return anthropic thinking config
expect(config).not.toBeNull()
expect(config?.thinking).toBeDefined()
expect((config?.thinking as Record<string, unknown>)?.type).toBe("enabled")
})
it("should still work for direct google provider", () => {
// #given direct google provider
// given direct google provider
const config = getThinkingConfig("google", "gemini-3-pro")
// #then should return google thinking config
// then should return google thinking config
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
})
it("should still work for amazon-bedrock provider", () => {
// #given amazon-bedrock provider with claude model
// given amazon-bedrock provider with claude model
const config = getThinkingConfig("amazon-bedrock", "claude-sonnet-4-5")
// #then should return bedrock thinking config
// then should return bedrock thinking config
expect(config).not.toBeNull()
expect(config?.reasoningConfig).toBeDefined()
})
it("should still work for google-vertex provider", () => {
// #given google-vertex provider
// given google-vertex provider
const config = getThinkingConfig("google-vertex", "gemini-3-pro")
// #then should return google-vertex thinking config
// then should return google-vertex thinking config
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
const vertexOptions = (config?.providerOptions as Record<string, unknown>)?.[
@@ -290,10 +290,10 @@ describe("think-mode switcher", () => {
})
it("should work for direct openai provider", () => {
// #given direct openai provider
// given direct openai provider
const config = getThinkingConfig("openai", "gpt-5")
// #then should return openai thinking config
// then should return openai thinking config
expect(config).not.toBeNull()
expect(config?.reasoning_effort).toBe("high")
})
@@ -326,44 +326,44 @@ describe("think-mode switcher", () => {
describe("Custom provider prefixes support", () => {
describe("getHighVariant with prefixes", () => {
it("should preserve vertex_ai/ prefix when getting high variant", () => {
// #given a model ID with vertex_ai/ prefix
// given a model ID with vertex_ai/ prefix
const variant = getHighVariant("vertex_ai/claude-sonnet-4-5")
// #then should return high variant with prefix preserved
// then should return high variant with prefix preserved
expect(variant).toBe("vertex_ai/claude-sonnet-4-5-high")
})
it("should preserve openai/ prefix when getting high variant", () => {
// #given a model ID with openai/ prefix
// given a model ID with openai/ prefix
const variant = getHighVariant("openai/gpt-5-2")
// #then should return high variant with prefix preserved
// then should return high variant with prefix preserved
expect(variant).toBe("openai/gpt-5-2-high")
})
it("should handle prefixes with dots in version numbers", () => {
// #given a model ID with prefix and dots
// given a model ID with prefix and dots
const variant = getHighVariant("vertex_ai/claude-opus-4.5")
// #then should normalize dots and preserve prefix
// then should normalize dots and preserve prefix
expect(variant).toBe("vertex_ai/claude-opus-4-5-high")
})
it("should handle multiple different prefixes", () => {
// #given various custom prefixes
// given various custom prefixes
expect(getHighVariant("azure/gpt-5")).toBe("azure/gpt-5-high")
expect(getHighVariant("bedrock/claude-sonnet-4-5")).toBe("bedrock/claude-sonnet-4-5-high")
expect(getHighVariant("custom-llm/gemini-3-pro")).toBe("custom-llm/gemini-3-pro-high")
})
it("should return null for prefixed models without high variant mapping", () => {
// #given prefixed model IDs without high variant mapping
// given prefixed model IDs without high variant mapping
expect(getHighVariant("vertex_ai/unknown-model")).toBeNull()
expect(getHighVariant("custom/llama-3-70b")).toBeNull()
})
it("should return null for already-high prefixed models", () => {
// #given prefixed model IDs that are already high
// given prefixed model IDs that are already high
expect(getHighVariant("vertex_ai/claude-opus-4-5-high")).toBeNull()
expect(getHighVariant("openai/gpt-5-2-high")).toBeNull()
})
@@ -371,20 +371,20 @@ describe("think-mode switcher", () => {
describe("isAlreadyHighVariant with prefixes", () => {
it("should detect -high suffix in prefixed models", () => {
// #given prefixed model IDs with -high suffix
// given prefixed model IDs with -high suffix
expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-5-high")).toBe(true)
expect(isAlreadyHighVariant("openai/gpt-5-2-high")).toBe(true)
expect(isAlreadyHighVariant("custom/gemini-3-pro-high")).toBe(true)
})
it("should return false for prefixed base models", () => {
// #given prefixed base model IDs without -high suffix
// given prefixed base model IDs without -high suffix
expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-5")).toBe(false)
expect(isAlreadyHighVariant("openai/gpt-5-2")).toBe(false)
})
it("should handle prefixed models with dots", () => {
// #given prefixed model IDs with dots
// given prefixed model IDs with dots
expect(isAlreadyHighVariant("vertex_ai/gpt-5.2")).toBe(false)
expect(isAlreadyHighVariant("vertex_ai/gpt-5.2-high")).toBe(true)
})
@@ -392,42 +392,42 @@ describe("think-mode switcher", () => {
describe("getThinkingConfig with prefixes", () => {
it("should return null for custom providers (not in THINKING_CONFIGS)", () => {
// #given custom provider with prefixed Claude model
// given custom provider with prefixed Claude model
const config = getThinkingConfig("dia-llm", "vertex_ai/claude-sonnet-4-5")
// #then should return null (custom provider not in THINKING_CONFIGS)
// then should return null (custom provider not in THINKING_CONFIGS)
expect(config).toBeNull()
})
it("should work with prefixed models on known providers", () => {
// #given known provider (anthropic) with prefixed model
// given known provider (anthropic) with prefixed model
// This tests that the base model name is correctly extracted for capability check
const config = getThinkingConfig("anthropic", "custom-prefix/claude-opus-4-5")
// #then should return thinking config (base model is capable)
// then should return thinking config (base model is capable)
expect(config).not.toBeNull()
expect(config?.thinking).toBeDefined()
})
it("should return null for prefixed models that are already high", () => {
// #given prefixed already-high model
// given prefixed already-high model
const config = getThinkingConfig("anthropic", "vertex_ai/claude-opus-4-5-high")
// #then should return null
// then should return null
expect(config).toBeNull()
})
})
describe("Real-world custom provider scenario", () => {
it("should handle LLM proxy with vertex_ai prefix correctly", () => {
// #given a custom LLM proxy provider using vertex_ai/ prefix
// given a custom LLM proxy provider using vertex_ai/ prefix
const providerID = "dia-llm"
const modelID = "vertex_ai/claude-sonnet-4-5"
// #when getting high variant
// when getting high variant
const highVariant = getHighVariant(modelID)
// #then should preserve the prefix
// then should preserve the prefix
expect(highVariant).toBe("vertex_ai/claude-sonnet-4-5-high")
// #and when checking if already high
@@ -437,17 +437,17 @@ describe("think-mode switcher", () => {
// #and when getting thinking config for custom provider
const config = getThinkingConfig(providerID, modelID)
// #then should return null (custom provider, not anthropic)
// then should return null (custom provider, not anthropic)
// This prevents applying incompatible thinking configs to custom providers
expect(config).toBeNull()
})
it("should not break when switching to high variant in think mode", () => {
// #given think mode switching vertex_ai/claude model to high variant
// given think mode switching vertex_ai/claude model to high variant
const original = "vertex_ai/claude-opus-4-5"
const high = getHighVariant(original)
// #then the high variant should be valid
// then the high variant should be valid
expect(high).toBe("vertex_ai/claude-opus-4-5-high")
// #and should be recognized as already high
@@ -462,10 +462,10 @@ describe("think-mode switcher", () => {
describe("Z.AI GLM-4.7 provider support", () => {
describe("getThinkingConfig for zai-coding-plan", () => {
it("should return thinking config for glm-4.7", () => {
// #given zai-coding-plan provider with glm-4.7 model
// given zai-coding-plan provider with glm-4.7 model
const config = getThinkingConfig("zai-coding-plan", "glm-4.7")
// #then should return zai-coding-plan thinking config
// then should return zai-coding-plan thinking config
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
const zaiOptions = (config?.providerOptions as Record<string, unknown>)?.[
@@ -479,37 +479,37 @@ describe("think-mode switcher", () => {
})
it("should return thinking config for glm-4.6v (multimodal)", () => {
// #given zai-coding-plan provider with glm-4.6v model
// given zai-coding-plan provider with glm-4.6v model
const config = getThinkingConfig("zai-coding-plan", "glm-4.6v")
// #then should return zai-coding-plan thinking config
// then should return zai-coding-plan thinking config
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
})
it("should return null for non-GLM models on zai-coding-plan", () => {
// #given zai-coding-plan provider with unknown model
// given zai-coding-plan provider with unknown model
const config = getThinkingConfig("zai-coding-plan", "some-other-model")
// #then should return null
// then should return null
expect(config).toBeNull()
})
})
describe("HIGH_VARIANT_MAP for GLM", () => {
it("should NOT have high variant for glm-4.7 (thinking enabled by default)", () => {
// #given glm-4.7 model
// given glm-4.7 model
const variant = getHighVariant("glm-4.7")
// #then should return null (no high variant needed)
// then should return null (no high variant needed)
expect(variant).toBeNull()
})
it("should NOT have high variant for glm-4.6v", () => {
// #given glm-4.6v model
// given glm-4.6v model
const variant = getHighVariant("glm-4.6v")
// #then should return null
// then should return null
expect(variant).toBeNull()
})
})