kioku-cli 0.4.1.0 → 0.5.0.0
raw patch · 4 files changed
+70/−18 lines, 4 filesdep ~kioku-apidep ~kioku-clidep ~kioku-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: kioku-api, kioku-cli, kioku-core, kioku-migrations
API changes (from Hackage documentation)
Files
- CHANGELOG.md +8/−0
- kioku-cli.cabal +8/−8
- src/Kioku/Cli/Commands/Recall.hs +19/−9
- test/Kioku/Cli/ParserSpec.hs +35/−1
CHANGELOG.md view
@@ -1,5 +1,13 @@ # Changelog +## 0.5.0.0 — 2026-08-22++### Fixed++- `kioku recall --strategy` now uses `Kioku.Api.Recall`'s canonical parser, enumeration, rendered+ spellings, and invalid-value diagnostic. Accepted commands and the default remain unchanged;+ the CLI no longer carries a second case expression or help-text list that can drift.+ ## 0.4.1.0 — 2026-08-18 ### Changed
kioku-cli.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: kioku-cli-version: 0.4.1.0+version: 0.5.0.0 synopsis: kioku command-line interface description: Command-line entry point for kioku demos and operational commands.@@ -76,8 +76,8 @@ , containers >=0.6 && <0.8 , directory >=1.3 && <1.4 , effectful >=2.5 && <2.7- , kioku-api ^>=0.4.1.0- , kioku-core ^>=0.4.1.0+ , kioku-api ^>=0.5.0.0+ , kioku-core ^>=0.5.0.0 , kiroku-store ^>=0.8.0.0 , optparse-applicative >=0.18 && <0.20 , text >=2.1 && <2.2@@ -90,7 +90,7 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: , base >=4.21 && <5- , kioku-cli ^>=0.4.1.0+ , kioku-cli ^>=0.5.0.0 test-suite kioku-cli-test import: warnings, shared@@ -110,10 +110,10 @@ build-depends: , base >=4.21 && <5 , effectful >=2.5 && <2.7- , kioku-api ^>=0.4.1.0- , kioku-cli ^>=0.4.1.0- , kioku-core ^>=0.4.1.0- , kioku-migrations:test-support ^>=0.4.1.0+ , kioku-api ^>=0.5.0.0+ , kioku-cli ^>=0.5.0.0+ , kioku-core ^>=0.5.0.0+ , kioku-migrations:test-support ^>=0.5.0.0 , kiroku-store ^>=0.8.0.0 , optparse-applicative >=0.18 , process >=1.6 && <1.7
src/Kioku/Cli/Commands/Recall.hs view
@@ -17,6 +17,9 @@ -- @kioku recall --scope mori@ to a fraction of its rows, with no compiler to warn and a zero exit -- status, which is the direction @docs\/adr\/an-explicit-recall-target-replaces-the-overloaded-scope.md@ -- records as the unsafe one.+--+-- The strategy spelling, enumeration, and invalid-value diagnostic are owned by+-- "Kioku.Api.Recall"; this module only adapts that vocabulary to optparse-applicative. module Kioku.Cli.Commands.Recall ( RecallOptions (..), recallOptionsParser,@@ -27,6 +30,7 @@ ) where +import Data.Bifunctor (first) import Data.Text (Text) import Data.Text qualified as Text import Kioku.Api.Access (memoryContextSpace, memorySpaceIdText)@@ -37,7 +41,16 @@ import Kioku.Cli.Options (boundedIntReader) import Kioku.Cli.Scope (parseNamespaceOnly, parseScope) import Kioku.Memory.Embedding (EmbeddingConfig (..), resolveEmbeddingConfig, toEmbeddingModel)-import Kioku.Recall (RecallHit (..), RecallStrategy (..), RecallTarget (..), mkRecallQuery, recall)+import Kioku.Recall+ ( RecallHit (..),+ RecallStrategy (..),+ RecallTarget (..),+ allRecallStrategies,+ mkRecallQuery,+ parseRecallStrategy,+ recall,+ recallStrategyText,+ ) import Kioku.Recall.Capability (detectVectorCapability) import Kiroku.Store.Connection (defaultConnectionSettings) import Options.Applicative@@ -60,9 +73,9 @@ <$> (Text.pack <$> argument str (metavar "QUERY")) <*> recallTargetParser <*> option- (eitherReader parseStrategy)+ (eitherReader (first Text.unpack . parseRecallStrategy . Text.pack)) ( long "strategy"- <> metavar "keyword|embedding|hybrid"+ <> metavar strategyMetavar <> value Hybrid <> help "Recall strategy" )@@ -182,12 +195,9 @@ Right (Right []) -> putStrLn "(no matches)" Right (Right hits) -> mapM_ (printHit opts.showScores) (zip [(1 :: Int) ..] hits) -parseStrategy :: String -> Either String RecallStrategy-parseStrategy = \case- "keyword" -> Right Keyword- "embedding" -> Right Embedding- "hybrid" -> Right Hybrid- other -> Left ("unknown strategy: " <> other)+strategyMetavar :: String+strategyMetavar =+ Text.unpack (Text.intercalate "|" (recallStrategyText <$> allRecallStrategies)) printHit :: Bool -> (Int, RecallHit) -> IO () printHit showScores (index, hit)
test/Kioku/Cli/ParserSpec.hs view
@@ -17,7 +17,13 @@ import Kioku.Cli.Scope (parseScope) import Kioku.Id (genMemoryId, genSessionId, idText) import Kioku.Memory.Embedding.Worker (EmbeddingBackfillScope (..))-import Kioku.Recall (RecallTarget (..))+import Kioku.Recall+ ( RecallStrategy (..),+ RecallTarget (..),+ allRecallStrategies,+ parseRecallStrategy,+ recallStrategyText,+ ) import Options.Applicative import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (assertBool, testCase, (@?=))@@ -29,6 +35,7 @@ [ sessionIdTests, scopeTests, recallTargetTests,+ strategyTests, limitTests, demoGuardTests, redactionTests,@@ -176,6 +183,33 @@ assertBool ("failure should name the conflicting flag " <> rejected <> ": " <> err) (rejected `isInfixOf` err)++-- | The API owns the strategy wire spelling, accepted enumeration, and diagnostic. The CLI+-- adapts that vocabulary to optparse-applicative without restating any of it.+strategyTests :: TestTree+strategyTests =+ testGroup+ "recall strategy uses the API vocabulary"+ [ testCase "every API strategy parses to itself" do+ mapM_+ (\expected -> strategy ["--strategy", Text.unpack (recallStrategyText expected)] @?= Right expected)+ allRecallStrategies,+ testCase "omission still defaults to hybrid" do+ strategy [] @?= Right Hybrid,+ testCase "an invalid value uses the API diagnostic and accepted list" do+ let invalid = "fuzzy"+ expected = either Text.unpack (const "unexpected success") (parseRecallStrategy invalid)+ case strategy ["--strategy", Text.unpack invalid] of+ Right parsed -> assertBool ("invalid strategy parsed as " <> show parsed) False+ Left err ->+ assertBool+ ("CLI error does not contain the API diagnostic: " <> err)+ (expected `isInfixOf` err)+ ]+ where+ strategy extra =+ fmap (.strategy) $+ parseWith recallOptionsParser (["query", "--namespace-wide", "mori"] <> extra) -- | Out-of-range limits are a parse error, not a Postgres error (@--limit -1@ used to reach -- SQL and come back as @LIMIT must not be negative@).