packages feed

shikumi 0.1.0.0 → 0.1.0.1

raw patch · 7 files changed

+54/−42 lines, 7 filesdep ~baikaidep ~baikai-claudedep ~baikai-effectfulPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: baikai, baikai-claude, baikai-effectful, baikai-openai, shikumi

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -2,6 +2,16 @@  ## Unreleased +## 0.1.0.1 - 2026-06-21++### Fixed++- Adapted `Shikumi.Error.fromBaikaiError` and streaming response reassembly to the baikai 0.2 API.++### Changed++- Constrained baikai package dependencies to the 0.2 series for Hackage builds.+ ## 0.1.0.0 - 2026-06-13  ### Added
shikumi.cabal view
@@ -1,6 +1,6 @@ cabal-version:   3.4 name:            shikumi-version:         0.1.0.0+version:         0.1.0.1 synopsis:        Typed, structured, evaluable LM programs over baikai category:        AI description:@@ -52,10 +52,10 @@    build-depends:     , aeson-    , baikai-    , baikai-claude-    , baikai-effectful-    , baikai-openai+    , baikai             >=0.2  && <0.3+    , baikai-claude      >=0.2  && <0.3+    , baikai-effectful   >=0.2  && <0.3+    , baikai-openai      >=0.2  && <0.3     , base               >=4.20 && <5     , base64-bytestring     , bytestring@@ -108,10 +108,10 @@    build-depends:     , aeson-    , baikai-    , baikai-claude-    , baikai-effectful-    , baikai-openai+    , baikai             >=0.2      && <0.3+    , baikai-claude      >=0.2      && <0.3+    , baikai-effectful   >=0.2      && <0.3+    , baikai-openai      >=0.2      && <0.3     , base     , base64-bytestring     , bytestring@@ -121,7 +121,7 @@     , generic-lens     , lens     , QuickCheck-    , shikumi            ^>=0.1.0.0+    , shikumi            ^>=0.1.0.1     , stm     , streamly-core     , tasty
src/Shikumi/Error.hs view
@@ -11,7 +11,7 @@   ) where -import Baikai.Error (BaikaiError (..))+import Baikai.Error (BaikaiError (..), ErrorCategory (..)) import Data.Text (Text) import Data.Text qualified as T @@ -37,19 +37,20 @@   deriving stock (Eq, Show)  -- | Total mapping from baikai's transport-level errors into shikumi's--- vocabulary. baikai's constructors are 'ProviderError', 'RequestInvalid',--- 'DecodeError', and 'ProcessError'.------ 'RequestInvalid' maps to 'SchemaMismatch' because in baikai a malformed request--- is almost always bad schema/parameters; 'DecodeError' maps to 'InvalidJSON'--- because baikai's decode failures are JSON parse failures of the provider--- response. These two judgments are the only non-mechanical choices.+-- vocabulary. Invalid requests map to 'SchemaMismatch' because in baikai a+-- malformed request is almost always bad schema/parameters; decode failures+-- map to 'InvalidJSON' because baikai's decode failures are JSON parse+-- failures of the provider response. fromBaikaiError :: BaikaiError -> ShikumiError-fromBaikaiError = \case-  ProviderError t -> ProviderFailure t-  RequestInvalid t -> SchemaMismatch ("invalid request: " <> t)-  DecodeError t -> InvalidJSON t-  ProcessError n t -> ProviderFailure ("process exited " <> T.pack (show n) <> ": " <> t)+fromBaikaiError e = case category e of+  DecodeFailure -> InvalidJSON (message e)+  InvalidRequest -> SchemaMismatch ("invalid request: " <> message e)+  ProcessFailure ->+    ProviderFailure $+      case exitCode e of+        Just n -> "process exited " <> T.pack (show n) <> ": " <> message e+        Nothing -> message e+  _ -> ProviderFailure (message e)  -- | Which errors are worth retrying. Provider/transport failures and timeouts are -- transient; decode, schema, validation, and budget errors are deterministic and
src/Shikumi/Stream.hs view
@@ -183,8 +183,8 @@   [] -> synthResponse (fromMaybe "" (firstTextEnd evs))   where     terminalPayloads =-      [p | EventDone (TerminalPayload _ (AssistantMessage p)) <- evs]-        ++ [p | EventError (TerminalPayload _ (AssistantMessage p)) <- evs]+      [p | EventDone TerminalPayload {message = AssistantMessage p} <- evs]+        ++ [p | EventError TerminalPayload {message = AssistantMessage p} <- evs]  -- | A response carrying @t@ as its single assistant text block. synthResponse :: Text -> Response
test/ErrorSpec.hs view
@@ -1,9 +1,9 @@ -- | Pins the 'BaikaiError' -> 'ShikumiError' mapping and the 'isTransient'--- classification. Deliberately breaking the mapping (e.g. mapping 'DecodeError'+-- classification. Deliberately breaking the mapping (e.g. mapping 'decodeError' -- to 'ProviderFailure') makes this group fail. module ErrorSpec (tests) where -import Baikai.Error (BaikaiError (..))+import Baikai.Error (decodeError, invalidRequest, processError, providerError) import Shikumi.Error   ( ShikumiError (..),     fromBaikaiError,@@ -16,14 +16,14 @@ tests =   testGroup     "ErrorSpec"-    [ testCase "maps ProviderError -> ProviderFailure" $-        fromBaikaiError (ProviderError "x") @?= ProviderFailure "x",-      testCase "maps DecodeError -> InvalidJSON" $-        fromBaikaiError (DecodeError "y") @?= InvalidJSON "y",-      testCase "maps RequestInvalid -> SchemaMismatch" $-        fromBaikaiError (RequestInvalid "z") @?= SchemaMismatch "invalid request: z",-      testCase "maps ProcessError -> ProviderFailure" $-        fromBaikaiError (ProcessError 2 "boom") @?= ProviderFailure "process exited 2: boom",+    [ testCase "maps providerError -> ProviderFailure" $+        fromBaikaiError (providerError "x") @?= ProviderFailure "x",+      testCase "maps decodeError -> InvalidJSON" $+        fromBaikaiError (decodeError "y") @?= InvalidJSON "y",+      testCase "maps invalidRequest -> SchemaMismatch" $+        fromBaikaiError (invalidRequest "z") @?= SchemaMismatch "invalid request: z",+      testCase "maps processError -> ProviderFailure" $+        fromBaikaiError (processError 2 "boom") @?= ProviderFailure "process exited 2: boom",       testCase "isTransient classification" $ do         isTransient (ProviderFailure "") @?= True         isTransient (Timeout "") @?= True
test/StreamSpec.hs view
@@ -19,6 +19,7 @@     StartPayload (..),     StopReason (..),     TerminalPayload (..),+    doneTerminal,     _Context,     _Model,     _Options,@@ -106,7 +107,7 @@ -- | The 'Response' assembled from a stream's terminal event. terminalResponse :: [AssistantMessageEvent] -> Response terminalResponse evs =-  case [p | EventDone (TerminalPayload _ (AssistantMessage p)) <- evs] of+  case [p | EventDone TerminalPayload {message = AssistantMessage p} <- evs] of     (p : _) -> _Response & #message .~ p     [] -> mkResponse "" @@ -121,7 +122,7 @@   ]     ++ [TextDelta (DeltaPayload 0 d) | d <- deltas]     ++ [ TextEnd (BlockEndPayload 0 (T.concat deltas)),-         EventDone (TerminalPayload Stop (AssistantMessage (payloadWith terminalText)))+         EventDone (doneTerminal Stop (AssistantMessage (payloadWith terminalText)))        ]   where     payloadWith t = (_Response ^. #message) & #content .~ V.singleton (AssistantText (_TextContent & #text .~ t))
test/StubProvider.hs view
@@ -95,7 +95,7 @@     TextStart IndexPayload {contentIndex = 0},     TextDelta DeltaPayload {contentIndex = 0, delta = t},     TextEnd BlockEndPayload {contentIndex = 0, content = t},-    EventDone TerminalPayload {reason = Stop, message = AssistantMessage (stubPayloadWith t)}+    EventDone (doneTerminal Stop (AssistantMessage (stubPayloadWith t)))   ]  -- | Build an isolated registry from a @complete@ implementation, reusing the@@ -122,7 +122,7 @@ costStubRegistry c t =   mkRegistry t (\_ _ _ -> pure (stubResponse t & #message . #usage . #cost . #usd .~ c)) --- | A registry whose @complete@ throws 'ProviderError' (a transient failure) the+-- | A registry whose @complete@ throws 'providerError' (a transient failure) the -- first @failTimes@ calls, then returns the given text. The 'IORef' records the -- total number of attempts (used by the retry tests). failingStubRegistry :: IORef Int -> Int -> Text -> IO ProviderRegistry@@ -130,17 +130,17 @@   mkRegistry t $ \_ _ _ -> do     n <- atomicModifyIORef' ref (\k -> (k + 1, k + 1))     if n <= failTimes-      then throwIO (ProviderError ("stub transient failure #" <> T.pack (show n)))+      then throwIO (providerError ("stub transient failure #" <> T.pack (show n)))       else pure (stubResponse t) --- | A registry whose @complete@ always throws 'RequestInvalid' (a non-transient+-- | A registry whose @complete@ always throws 'invalidRequest' (a non-transient -- failure that maps to 'Shikumi.Error.SchemaMismatch'). The 'IORef' records the -- number of attempts (a retry must not increase it). invalidStubRegistry :: IORef Int -> IO ProviderRegistry invalidStubRegistry ref =   mkRegistry "" $ \_ _ _ -> do     _ <- atomicModifyIORef' ref (\k -> (k + 1, k + 1))-    throwIO (RequestInvalid "stub bad request")+    throwIO (invalidRequest "stub bad request")  -- | A registry whose @complete@ records observed concurrency: it bumps @cur@ on -- entry (updating the running maximum in @mx@), sleeps briefly, and decrements on