baikai 0.3.1.0 → 0.4.1.0
raw patch · 9 files changed
Files
- CHANGELOG.md +86/−0
- baikai.cabal +2/−1
- gen/GenModelsCore.hs +20/−0
- src/Baikai/Interactive.hs +6/−2
- src/Baikai/Models/Generated.hs +40/−0
- src/Baikai/ThinkingLevel.hs +15/−8
- test/InteractiveSpec.hs +1/−0
- test/Main.hs +2/−0
- test/ThinkingLevelSpec.hs +36/−0
CHANGELOG.md view
@@ -7,6 +7,92 @@ ## [Unreleased] +## [baikai 0.4.1.0] - 2026-07-20++### Changed++- Version bump only; no library API or code changes. Released so the umbrella+ release tag `baikai-0.4.1.0` names a fresh core version alongside the breaking+ `baikai-claude` / `baikai-openai` 0.4.0.0 releases, matching the tag+ convention downstream consumers pin against.++## [baikai-claude 0.4.0.0] - 2026-07-20++### Changed++- **Breaking:** `claudeCliCommand` now takes the `Options` record and forwards+ `Options.thinking` to batch `claude -p` as `--effort <level>` (`minimal`+ collapses to `low`, matching the interactive launcher and the claude CLI's+ lack of a `minimal` value). `thinking = Nothing` emits no effort flag, keeping+ existing argv byte-for-byte. The added parameter is a PVP-major signature+ change.++## [baikai-openai 0.4.0.0] - 2026-07-20++### Changed++- **Breaking:** `codexCliCommand` now takes the `Options` record and forwards+ `Options.thinking` to `codex exec` as `-c model_reasoning_effort=<level>` for+ all six effort levels. `thinking = Nothing` emits no override, keeping+ existing argv byte-for-byte. The added parameter is a PVP-major signature+ change.++## [baikai 0.4.0.0] - 2026-07-20++### Added++- Added `ThinkingXHigh` and `ThinkingMax` to the exported `ThinkingLevel`+ vocabulary and added a defaulted `InteractiveLaunchRequest.effort` field.+ Extending the closed sum type is a PVP-major API change for downstream+ exhaustive matches.++## [baikai-claude 0.3.0.2] - 2026-07-20++### Added++- Added `--effort` rendering to interactive Claude Code launches and preserved+ `xhigh` / `max` on native adaptive Anthropic API requests, with larger fixed+ budgets for manual-thinking models.++### Changed++- Bumped the internal `baikai` dependency bound to `^>=0.4.0` for the+ baikai 0.4.0.0 release.++## [baikai-openai 0.3.0.2] - 2026-07-20++### Added++- Added `model_reasoning_effort` overrides to interactive Codex launches and+ preserved `xhigh` / `max` in native OpenAI request JSON; non-native+ OpenAI-compatible request shapes continue to clamp them to `high`.++### Changed++- Bumped the internal `baikai` dependency bound to `^>=0.4.0` for the+ baikai 0.4.0.0 release.++## [baikai-trace-otel 0.3.0.2] - 2026-07-20++### Changed++- Bumped the internal `baikai` dependency bound to `^>=0.4.0` for the+ baikai 0.4.0.0 release. No API changes.++## [baikai-effectful 0.3.0.2] - 2026-07-20++### Changed++- Bumped the internal `baikai` dependency bound to `^>=0.4.0` for the+ baikai 0.4.0.0 release. No API changes.++## [baikai-kit 0.1.0.3] - 2026-07-20++### Changed++- Bumped the internal `baikai` dependency bound to `^>=0.4.0` for the+ baikai 0.4.0.0 release. No API changes.+ ## [baikai 0.3.1.0] - 2026-07-15 ### Added
baikai.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: baikai-version: 0.3.1.0+version: 0.4.1.0 synopsis: Unified Haskell interface for multiple AI providers description: baikai provides a unified, provider-agnostic Haskell interface for working@@ -151,6 +151,7 @@ InteractiveSpec StreamSpec SurfaceSpec+ ThinkingLevelSpec TraceSpec UsageSpec
gen/GenModelsCore.hs view
@@ -322,6 +322,7 @@ dropTrailingEmpty ( header ++ concatMap (renderEntry . snd) entries+ ++ renderAllModels (map (ident . snd) entries) ) where dropTrailingEmpty = \case@@ -371,6 +372,25 @@ "import Data.Ratio ((%))", "" ]++-- | Render the @allModels@ binding: every generated model in one list, in the+-- same (identifier-sorted) order as the declarations above. Consumers can fold+-- or filter this instead of hand-listing bindings, so a catalog change flows+-- through automatically.+renderAllModels :: [Text] -> [Text]+renderAllModels idents =+ "-- | Every model in the generated catalog, in declaration order."+ : "allModels :: [Model]"+ : "allModels ="+ : case idents of+ [] -> [" []"]+ _ ->+ [ " " <> prefix <> ident <> suffix+ | (position, ident) <- zip [0 :: Int ..] idents,+ let prefix = if position == 0 then "[ " else " ",+ let suffix = if position == length idents - 1 then "" else ","+ ]+ ++ [" ]"] renderEntry :: GeneratedEntry -> [Text] renderEntry g =
src/Baikai/Interactive.hs view
@@ -15,6 +15,7 @@ extraDirs, safety, extraArgs,+ effort, InteractiveSafety (..), CodexSandboxMode (..), CodexApprovalPolicy (..),@@ -31,6 +32,7 @@ where import Baikai.Prelude+import Baikai.ThinkingLevel (ThinkingLevel) import System.Exit (ExitCode) -- | Local interactive provider families that Baikai knows how to@@ -56,7 +58,8 @@ workingDir :: !(Maybe FilePath), extraDirs :: ![FilePath], safety :: !InteractiveSafety,- extraArgs :: ![Text]+ extraArgs :: ![Text],+ effort :: !(Maybe ThinkingLevel) } deriving stock (Eq, Show, Generic) @@ -98,7 +101,8 @@ workingDir = Nothing, extraDirs = [], safety = DefaultSafety,- extraArgs = []+ extraArgs = [],+ effort = Nothing } interactiveLaunchResult :: InteractiveProvider -> ExitCode -> InteractiveLaunchResult
src/Baikai/Models/Generated.hs view
@@ -841,3 +841,43 @@ headers = Map.empty, compat = CompatNone }++-- | Every model in the generated catalog, in declaration order.+allModels :: [Model]+allModels =+ [ anthropic_claude_fable_5,+ anthropic_claude_haiku_4_5,+ anthropic_claude_opus_4_5,+ anthropic_claude_opus_4_6,+ anthropic_claude_opus_4_7,+ anthropic_claude_opus_4_8,+ anthropic_claude_sonnet_4_5,+ anthropic_claude_sonnet_4_6,+ anthropic_claude_sonnet_5,+ deepseek_deepseek_chat,+ deepseek_deepseek_reasoner,+ openai_gpt_4_1,+ openai_gpt_4_1_mini,+ openai_gpt_4_1_nano,+ openai_gpt_4o,+ openai_gpt_4o_mini,+ openai_gpt_5,+ openai_gpt_5_1,+ openai_gpt_5_2,+ openai_gpt_5_4,+ openai_gpt_5_4_mini,+ openai_gpt_5_4_nano,+ openai_gpt_5_5,+ openai_gpt_5_6,+ openai_gpt_5_6_luna,+ openai_gpt_5_6_sol,+ openai_gpt_5_6_terra,+ openai_gpt_5_mini,+ openai_gpt_5_nano,+ openai_o1,+ openai_o3,+ openai_o3_mini,+ openai_o4_mini,+ openrouter_anthropic_claude_sonnet_4,+ openrouter_openai_gpt_4o_mini+ ]
src/Baikai/ThinkingLevel.hs view
@@ -2,10 +2,10 @@ -- | Provider-agnostic reasoning-effort preference. ----- Each provider maps the value to its own primitive: OpenAI uses--- @reasoning_effort: "minimal" | "low" | "medium" | "high"@;--- Anthropic uses a token budget on its @thinking@ field.--- 'thinkingTokenBudget' provides the recommended budget for the+-- Each provider maps the value to its own primitive. The canonical+-- rendering spans @minimal@ through @max@, while provider boundaries+-- may preserve, translate, or clamp values according to their APIs.+-- 'thinkingTokenBudget' provides the recommended budget for -- token-based providers. module Baikai.ThinkingLevel ( ThinkingLevel (..),@@ -19,24 +19,29 @@ import GHC.Generics (Generic) import Numeric.Natural (Natural) --- | The four buckets pi-mono settled on. Coarse enough that callers--- do not need to learn each provider's TTL conventions, fine enough--- to influence behaviour in a meaningful way.+-- | Provider-neutral reasoning-effort buckets, ordered from least to+-- most effort. Coarse enough that callers do not need to learn each+-- provider's vocabulary, fine enough to influence behaviour in a+-- meaningful way. data ThinkingLevel = ThinkingMinimal | ThinkingLow | ThinkingMedium | ThinkingHigh+ | ThinkingXHigh+ | ThinkingMax deriving stock (Eq, Ord, Show, Generic) deriving anyclass (FromJSON, ToJSON) --- | The wire string OpenAI's @reasoning_effort@ field expects.+-- | Render the canonical Baikai name for a reasoning-effort level. renderThinkingLevel :: ThinkingLevel -> Text renderThinkingLevel = \case ThinkingMinimal -> "minimal" ThinkingLow -> "low" ThinkingMedium -> "medium" ThinkingHigh -> "high"+ ThinkingXHigh -> "xhigh"+ ThinkingMax -> "max" -- | Recommended token budget for providers that take an explicit -- count (Anthropic's @thinking.budget_tokens@).@@ -46,3 +51,5 @@ ThinkingLow -> 2048 ThinkingMedium -> 8192 ThinkingHigh -> 16384+ ThinkingXHigh -> 24576+ ThinkingMax -> 32768
test/InteractiveSpec.hs view
@@ -27,6 +27,7 @@ req ^. #extraDirs @?= [] req ^. #safety @?= DefaultSafety req ^. #extraArgs @?= []+ req ^. #effort @?= Nothing providerRenderingTest :: TestTree providerRenderingTest =
test/Main.hs view
@@ -27,6 +27,7 @@ import Test.Tasty.HUnit (assertBool, testCase, (@?=)) import Test.Tasty.QuickCheck (Gen) import Test.Tasty.QuickCheck qualified as QC+import ThinkingLevelSpec qualified import TraceSpec qualified import UsageSpec qualified @@ -101,6 +102,7 @@ InteractiveSpec.tests, StreamSpec.tests, SurfaceSpec.tests,+ ThinkingLevelSpec.tests, TraceSpec.tests, UsageSpec.tests ]
+ test/ThinkingLevelSpec.hs view
@@ -0,0 +1,36 @@+module ThinkingLevelSpec (tests) where++import Baikai.ThinkingLevel+import Data.Text (Text)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))++tests :: TestTree+tests =+ testGroup+ "ThinkingLevel"+ [ testGroup "canonical rendering" renderTests,+ testGroup "token budgets" budgetTests+ ]++levels :: [(String, ThinkingLevel, Text, Integer)]+levels =+ [ ("minimal", ThinkingMinimal, "minimal", 1024),+ ("low", ThinkingLow, "low", 2048),+ ("medium", ThinkingMedium, "medium", 8192),+ ("high", ThinkingHigh, "high", 16384),+ ("xhigh", ThinkingXHigh, "xhigh", 24576),+ ("max", ThinkingMax, "max", 32768)+ ]++renderTests :: [TestTree]+renderTests =+ [ testCase name $ renderThinkingLevel level @?= expected+ | (name, level, expected, _) <- levels+ ]++budgetTests :: [TestTree]+budgetTests =+ [ testCase name $ thinkingTokenBudget level @?= fromInteger expected+ | (name, level, _, expected) <- levels+ ]