shikumi-tools 0.4.1.1 → 0.4.2.0
raw patch · 5 files changed
+104/−9 lines, 5 filesdep ~baikaidep ~shikumidep ~shikumi-cachePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: baikai, shikumi, shikumi-cache, shikumi-tools
API changes (from Hackage documentation)
- Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Fs.EditReq
- Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Fs.GlobReq
- Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Fs.GrepReq
- Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Fs.ReadReq
- Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Fs.WriteReq
- Shikumi.Tool.Builtin.Shell: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Shell.BashReq
- Shikumi.Tool.Builtin.Web: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Web.FetchReq
- Shikumi.Tool.Builtin.Web: instance Shikumi.Adapter.ToPrompt Shikumi.Tool.Builtin.Web.SearchReq
+ Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Fs.EditReq
+ Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Fs.GlobReq
+ Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Fs.GrepReq
+ Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Fs.ReadReq
+ Shikumi.Tool.Builtin.Fs: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Fs.WriteReq
+ Shikumi.Tool.Builtin.Shell: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Shell.BashReq
+ Shikumi.Tool.Builtin.Web: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Web.FetchReq
+ Shikumi.Tool.Builtin.Web: instance Shikumi.Adapter.Prompt.ToPrompt Shikumi.Tool.Builtin.Web.SearchReq
Files
- CHANGELOG.md +9/−0
- shikumi-tools.cabal +8/−7
- src/Shikumi/Agent/History.hs +2/−1
- test/Main.hs +3/−1
- test/SystemOneIntegrationSpec.hs +82/−0
CHANGELOG.md view
@@ -2,6 +2,15 @@ ## Unreleased +## 0.4.2.0 — 2026-11-02++### Changed++- Upgrade `mori://shinzui/baikai/packages/baikai` to `>=0.10.0.0 && <0.11`.++- Update internal dependency bounds for the breaking `shikumi 0.5.0.0` release.+- Omit provider structured data from agent summaries while retaining it in history.+ ## 0.4.1.1 — 2026-10-16 ### Changed
shikumi-tools.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: shikumi-tools-version: 0.4.1.1+version: 0.4.2.0 synopsis: Typed tools and ReAct agents for shikumi LM programs (EP-11) @@ -68,7 +68,7 @@ build-depends: aeson >=2.2 && <2.3,- baikai >=0.8.0.0 && <0.9,+ baikai >=0.10.0.0 && <0.11, base >=4.20 && <5, bytestring >=0.11 && <0.13, containers >=0.6 && <0.9,@@ -82,7 +82,7 @@ lens ^>=5.3, process >=1.6 && <1.7, regex-tdfa >=1.3 && <1.4,- shikumi ^>=0.4.1.1,+ shikumi ^>=0.5.0.0, text ^>=2.1, vector >=0.13 && <0.14, @@ -116,13 +116,14 @@ SchemaSpec SessionSpec ShellSpec+ SystemOneIntegrationSpec ToolOutputSpec ToolSpec WebSpec build-depends: aeson,- baikai >=0.8.0.0 && <0.9,+ baikai >=0.10.0.0 && <0.11, base, bytestring, containers,@@ -131,10 +132,10 @@ filepath, generic-lens, lens,- shikumi ^>=0.4.1.1,- shikumi-cache ^>=0.2.0.2,+ shikumi ^>=0.5.0.0,+ shikumi-cache ^>=0.2.1.0, shikumi-testing ^>=0.1.0.0,- shikumi-tools ^>=0.4.1.1,+ shikumi-tools ^>=0.4.2.0, tasty, tasty-hunit, text,
src/Shikumi/Agent/History.hs view
@@ -204,13 +204,14 @@ -- | Structural projection: provider-owned reasoning and unknown rich extensions -- never enter a summarizer request. The full audit retains all original bytes. renderSummaryEntry :: HistoryEntry -> Text-renderSummaryEntry (UserTurn p) = T.intercalate "\n" [case b of B.UserText (B.TextContent t) -> t; B.UserImage _ -> "[image omitted]" | b <- V.toList (p ^. #content)]+renderSummaryEntry (UserTurn p) = T.intercalate "\n" [case b of B.UserText (B.TextContent t) -> t; B.UserImage _ -> "[image omitted]"; B.UserData _ -> "[structured data omitted]" | b <- V.toList (p ^. #content)] renderSummaryEntry (Exchange p outputs correction) = T.intercalate "\n" (map block (V.toList (p ^. #content)) <> map output outputs <> maybe [] (\t -> ["Correction: " <> t]) correction) where block (B.AssistantText (B.TextContent t)) = t block (B.AssistantThinking t) | t ^. #redacted = "[redacted reasoning omitted]" | otherwise = t ^. #thinking <> "\n[reasoning continuation omitted]"+ block (B.AssistantData _) = "[structured data omitted]" block (B.AssistantToolCall c) = c ^. #name <> " " <> jsonText (c ^. #arguments) output (c, o) = c ^. #name
test/Main.hs view
@@ -19,6 +19,7 @@ import SchemaSpec qualified import SessionSpec qualified import ShellSpec qualified+import SystemOneIntegrationSpec qualified import Test.Tasty (defaultMain, testGroup) import ToolOutputSpec qualified import ToolSpec qualified@@ -29,7 +30,8 @@ defaultMain $ testGroup "shikumi-tools"- [ ResponsesSchemaSpec.tests,+ [ SystemOneIntegrationSpec.tests,+ ResponsesSchemaSpec.tests, ResponsesIntegrationSpec.tests, SessionSpec.tests, RLMSpec.tests,
+ test/SystemOneIntegrationSpec.hs view
@@ -0,0 +1,82 @@+module SystemOneIntegrationSpec (tests) where++import Baikai qualified as B+import Data.Aeson+import Data.Aeson.KeyMap qualified as KM+import Data.Map.Strict qualified as Map+import Data.Text qualified as T+import Effectful (runEff)+import Effectful.Dispatch.Dynamic (interpose)+import Effectful.Error.Static (runErrorNoCallStack)+import Shikumi.Adapter (stampTemperature)+import Shikumi.Decision+import Shikumi.Error+import Shikumi.LLM qualified as L+import Shikumi.LLM.Defaults+import Shikumi.Program+import Shikumi.Routing+import Shikumi.Schema (field, unField)+import Shikumi.Testing.DecisionFixtures+import Shikumi.Testing.Responses (fixtureOptions, withTransportOptions)+import Shikumi.Testing.SystemOne+import Test.Tasty+import Test.Tasty.HUnit++reply :: Value+reply =+ object+ [ "model" .= String "jev-latest",+ "usage" .= object ["input_tokens" .= (10 :: Int), "output_tokens" .= (3 :: Int)],+ "answers"+ .= object+ [ "urgent" .= object ["type" .= String "noul", "noul" .= (0.83 :: Double)],+ "severity" .= object ["type" .= String "score", "probabilities" .= object ["0" .= (0.1 :: Double), "1" .= (0.3 :: Double), "2" .= (0.6 :: Double)], "score" .= (1.5 :: Double), "confidence" .= (0.55 :: Double), "legend" .= object ["0" .= String "Minor", "1" .= String "Disruptive", "2" .= String "Blocking"]],+ "category" .= object ["type" .= String "choice", "probabilities" .= object ["billing" .= (0.2 :: Double), "technical" .= (0.8 :: Double)], "choice" .= String "technical", "confidence" .= (0.65 :: Double)]+ ]+ ]++tests :: TestTree+tests =+ testGroup+ "SystemOne"+ [ testCase "released provider sends state and criteria; defaults exempt" $+ withSystemOneFixture reply $ \model registry requests -> do+ let defaults = emptyRequestDefaults {defaultThinking = Just B.ThinkingHigh, defaultMaxTokens = Just 100}+ result <-+ runEff . runErrorNoCallStack @ShikumiError . runRouting model . L.runLLMWith registry . withTransportOptions fixtureOptions . withRequestDefaults defaults . routeLLM $+ runProgram (Predict assessmentSig emptyParams) (Ticket (field "Checkout is unavailable."))+ case result of+ Right (Assessment u s c) -> do+ case unField u of Noul value p _ -> do value @?= True; p @?= 0.83+ case unField s of Score value level _ confidence -> do value @?= 1.5; level @?= 2; confidence @?= Just 0.55+ case unField c of Choice value _ confidence -> do value @?= Technical; confidence @?= Just 0.65+ Left err -> assertFailure (show err)+ bodies <- requests+ bodies @?= [object ["model" .= String "jev-latest", "state" .= renderDecisionState assessmentSig (Ticket (field "Checkout is unavailable.")), "questions" .= Map.fromList [(judgmentField j, questionJSON j) | j <- judgmentsOf @Assessment]]],+ testCase "explicit temperature is terminal with zero HTTP requests" $+ withSystemOneFixture reply $ \model registry requests -> do+ result <-+ runEff . runErrorNoCallStack @ShikumiError . runRouting model . L.runLLMWith registry . withTransportOptions fixtureOptions . routeLLM . interpose (\_ -> \case L.Complete m c o -> L.complete m c (stampTemperature 0.7 o); L.Stream m c o -> L.stream m c o) $+ runProgram (Predict assessmentSig emptyParams) (Ticket (field "x"))+ assertBool "terminal refusal" (case result of Left (SchemaMismatch msg) -> "temperature" `T.isInfixOf` msg; _ -> False)+ requests >>= (@?= []),+ testCase "missing wire evidence or undeclared answers fail after one HTTP request" $ do+ let modifyAnswer name f = modifyObject "answers" (adjust (\case Object o -> Object (f o); v -> v) name) reply+ malformed = [modifyAnswer "category" (KM.delete "confidence"), modifyAnswer "severity" (KM.delete "score"), modifyAnswer "severity" (KM.delete "legend"), modifyObject "answers" (KM.insert "unexpected" (object ["type" .= String "noul", "noul" .= (0.5 :: Double)])) reply]+ mapM_+ ( \bad -> withSystemOneFixture bad $ \model registry requests -> do+ result <-+ runEff . runErrorNoCallStack @ShikumiError . runRouting model . L.runLLMWith registry . withTransportOptions fixtureOptions . routeLLM $+ runProgram (Predict assessmentSig emptyParams) (Ticket (field "x"))+ assertBool "terminal InvalidJSON" (case result of Left (InvalidJSON _) -> True; _ -> False)+ requests >>= (\xs -> length xs @?= 1)+ )+ malformed+ ]++adjust :: (a -> a) -> Key -> KM.KeyMap a -> KM.KeyMap a+adjust f k o = maybe o (\v -> KM.insert k (f v) o) (KM.lookup k o)++modifyObject :: Key -> (KM.KeyMap Value -> KM.KeyMap Value) -> Value -> Value+modifyObject key f (Object fields) = Object (adjust (\case Object o -> Object (f o); v -> v) key fields)+modifyObject _ _ v = v