shikumi-cache 0.1.2.1 → 0.1.2.2
raw patch · 3 files changed
+77/−7 lines, 3 filesdep ~baikaiPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: baikai
API changes (from Hackage documentation)
Files
- CHANGELOG.md +19/−0
- shikumi-cache.cabal +3/−3
- src/Shikumi/Cache/ResponseJSON.hs +55/−4
CHANGELOG.md view
@@ -2,6 +2,25 @@ ## Unreleased +## 0.1.2.2 — 2026-08-07++### Changed++- Upgraded the `baikai` dependency to the `0.5` series (`>=0.5 && <0.6`).++- `Shikumi.Cache.ResponseJSON`'s orphan `ToJSON`/`FromJSON` for+ `Baikai.Response.Response` are written out by hand instead of derived, and+ they neither write nor read baikai 0.5's new `evidence` field. A cache hit+ replays a stored response without any provider call, so carrying the+ original call's `ModelCallEvidence` would attribute a record of a real+ boundary crossing to a call that never made one. Decoding always yields+ `evidence = Nothing`.++ The encoded keys are otherwise unchanged, so entries written by a pre-0.5+ shikumi still read back and `currentKeyVersion` is untouched. (baikai+ deliberately ships no `FromJSON ModelCallEvidence`, so the derived instance+ could not have been kept regardless.)+ ## 0.1.2.1 - 2026-07-20 ### Changed
shikumi-cache.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: shikumi-cache-version: 0.1.2.1+version: 0.1.2.2 synopsis: Content-addressed response caching for shikumi (EP-6) category: AI description:@@ -45,7 +45,7 @@ build-depends: , aeson- , baikai >=0.4 && <0.5+ , baikai >=0.5 && <0.6 , base >=4.20 && <5 , blake3 , bytestring@@ -69,7 +69,7 @@ ghc-options: -threaded -with-rtsopts=-N build-depends: , aeson- , baikai >=0.4 && <0.5+ , baikai >=0.5 && <0.6 , base , bytestring , containers
src/Shikumi/Cache/ResponseJSON.hs view
@@ -23,9 +23,21 @@ -- repetends; it never affects the typed-output guarantee, which is decoded -- from the assistant __text__ ('AssistantContent', which round-trips -- exactly) — cost is metadata.--- * 'AssistantPayload' / 'Response' use @defaultOptions@ (matching baikai's+-- * 'AssistantPayload' uses @defaultOptions@ (matching baikai's -- @deriving anyclass ToJSON@).+-- * 'Response' is written out by hand with the same keys @defaultOptions@+-- produced, minus @evidence@ — see below. --+-- __'Response' does not cache its 'Baikai.Evidence.ModelCallEvidence'.__ Since+-- baikai 0.5 a 'Response' may carry the evidence record for the call that+-- produced it. That record describes /one/ crossing of the provider boundary; a+-- cache hit is precisely the case where no such crossing happened, so replaying+-- a stored record would attribute another call's evidence to this one — the+-- exact misattribution the evidence vocabulary exists to prevent. The encoder+-- therefore drops the field and the decoder always yields @evidence = Nothing@.+-- Dropping it also keeps the encoding byte-identical to what pre-0.5 shikumi+-- wrote, so cache entries written by an older build still read back.+-- -- This module is the __single home__ for these orphans across the whole -- framework. EP-7's @Shikumi.Trace.ResponseJSON@ re-exports them from here rather -- than defining its own copy, so no module that imports both the cache and the@@ -45,9 +57,11 @@ camelTo2, defaultOptions, genericParseJSON,- genericToJSON,+ object, withObject, (.:),+ (.:?),+ (.=), ) import Data.Aeson.Types (Parser) import Data.Scientific (Scientific)@@ -85,7 +99,44 @@ parseJSON = genericParseJSON defaultOptions instance ToJSON Response where- toJSON = genericToJSON defaultOptions+ toJSON+ Response+ { message = m,+ model = mdl,+ api = a,+ provider = p,+ responseId = rid,+ latencyMs = ms,+ errorInfo = e,+ evidence = _+ } =+ object+ [ "message" .= m,+ "model" .= mdl,+ "api" .= a,+ "provider" .= p,+ "responseId" .= rid,+ "latencyMs" .= ms,+ "errorInfo" .= e+ ] instance FromJSON Response where- parseJSON = genericParseJSON defaultOptions+ parseJSON = withObject "Response" $ \o -> do+ m <- o .: "message"+ mdl <- o .: "model"+ a <- o .: "api"+ p <- o .: "provider"+ rid <- o .:? "responseId"+ ms <- o .: "latencyMs"+ e <- o .:? "errorInfo"+ pure+ Response+ { message = m,+ model = mdl,+ api = a,+ provider = p,+ responseId = rid,+ latencyMs = ms,+ errorInfo = e,+ evidence = Nothing+ }