agentic-openai 0.2.0.5 → 0.2.1.0
raw patch · 4 files changed
+46/−15 lines, 4 filesdep ~agenticdep ~agentic-aesondep ~agentic-ioPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: agentic, agentic-aeson, agentic-io, agentic-openai
API changes (from Hackage documentation)
Files
- CHANGELOG.md +5/−0
- agentic-openai.cabal +9/−9
- test-live/Live.hs +2/−2
- test/Spec.hs +30/−4
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Changelog for agentic-openai +## 0.2.1.0 - 2026-11-06++* Follow Agentic's `Structure`/`Outline` API and fallible model compilation.+ Provider wire schemas and protocols are unchanged.+ ## 0.2.0.5 - 2026-10-06 * No changes; released alongside agentic 0.2.0.5.
agentic-openai.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: agentic-openai-version: 0.2.0.5+version: 0.2.1.0 synopsis: OpenAI as the System Two provider for agentic description: Runs agentic's draft steps on OpenAI models through the Responses API, with strict structured outputs and tools, and can stand in as System One.@@ -38,8 +38,8 @@ hs-source-dirs: src exposed-modules: Agentic.OpenAI build-depends:- , agentic ==0.2.*- , agentic-aeson ==0.2.*+ , agentic >=0.2.1 && <0.3+ , agentic-aeson >=0.2.1 && <0.3 , aeson >=2.1 && <2.3 , base >=4.18 && <5 , bytestring >=0.11 && <0.13@@ -53,9 +53,9 @@ hs-source-dirs: test main-is: Spec.hs build-depends:- , agentic ==0.2.*- , agentic-aeson ==0.2.*- , agentic-openai ==0.2.*+ , agentic >=0.2.1 && <0.3+ , agentic-aeson >=0.2.1 && <0.3+ , agentic-openai >=0.2.1 && <0.3 , aeson >=2.1 && <2.3 , base >=4.18 && <5 , hspec >=2.10 && <3@@ -67,9 +67,9 @@ hs-source-dirs: test-live main-is: Live.hs build-depends:- , agentic ==0.2.*- , agentic-openai ==0.2.*- , agentic-io ==0.2.*+ , agentic >=0.2.1 && <0.3+ , agentic-openai >=0.2.1 && <0.3+ , agentic-io >=0.2.1 && <0.3 , base >=4.18 && <5 , hspec >=2.10 && <3 , text >=2.0 && <2.2
test-live/Live.hs view
@@ -29,13 +29,13 @@ "How much the audience groans" [option Mild "A polite smile", option Solid "An audible groan", option Unbearable "People get up and leave"] -deriving via Enumeration Groan instance Contract Groan+instance Contract Groan where contract = enumeration newtype Rating = Rating Int deriving (Show, Eq) instance Contract Rating where- contract = mapCodec Rating (\(Rating n) -> n) (between 1 10 contract)+ contract = mapStructure Rating (\(Rating n) -> n) (between 1 10 contract) main :: IO () main = do
test/Spec.hs view
@@ -1,8 +1,10 @@ module Main (main) where import Agentic+import Agentic.Scripted (modelContract) import Agentic.Runtime (Conversation (..))-import Agentic.Schema (Shape (..))+import Agentic.Schema (Schema(..), Field(..), Shape (..))+import Agentic.JsonSchema (objectSchema) import Agentic.Aeson (toAeson) import Agentic.OpenAI import qualified Data.Aeson as J@@ -22,6 +24,9 @@ data Board = Board {top :: Row, middle :: Row, bottom :: Row} deriving (Generic, Show, Contract) +data Box a = Box { value :: a } deriving (Generic, Contract)+data Repeated = Repeated { one :: Box Int, two :: Box Int } deriving (Generic, Contract)+ conversation :: Conversation conversation = Conversation@@ -29,8 +34,8 @@ , instruction = "Suggest 3 dinosaurs" , input = Null , inputSchema = schemaOf SNull- , tools = [ToolSpec "search" "Search the fossil database" ((contract @Text).schema)]- , outputSchema = (contract @[Text]).schema+ , tools = [ToolSpec "search" "Search the fossil database" ((modelContract @Text).schema)]+ , outputSchema = (modelContract @[Text]).schema , history = [] } @@ -57,11 +62,32 @@ ) it "names the schema after its type, and shares repeated types through $defs" $ do- let format = at "format" (at "text" (body conversation {outputSchema = (contract @Board).schema}))+ let format = at "format" (at "text" (body conversation {outputSchema = (modelContract @Board).schema})) schema = at "schema" format at "name" format `shouldBe` J.String "Board" at "top" (at "properties" schema) `shouldBe` fromJust (J.decode "{\"$ref\":\"#/$defs/Row\"}") KeyMap.keys (case at "$defs" schema of J.Object o -> o; _ -> mempty) `shouldMatchList` ["Row", "Square"]++ it "uses safe shared-definition keys for applied type names" $ do+ let schema = toAeson (objectSchema (modelContract @Repeated).schema)+ at "$ref" (at "one" (at "properties" schema)) `shouldBe` J.String "#/$defs/Box_Int"+ at "$ref" (at "two" (at "properties" schema)) `shouldBe` J.String "#/$defs/Box_Int"+ at "type" (at "Box_Int" (at "$defs" schema)) `shouldBe` J.String "object"++ it "keeps colliding sanitized names and pointer punctuation distinct" $ do+ let a = Schema (Just "Box Int") Nothing [] SInteger+ b = Schema (Just "Box_Int") Nothing [] (SString Nothing)+ c = Schema (Just "A/B~C") Nothing [] SBool+ root = schemaOf (SObject [Field n ty True | (n, ty) <- [("a1",a),("a2",a),("b1",b),("b2",b),("c1",c),("c2",c)]])+ schema = toAeson (objectSchema root)+ defs = at "$defs" schema+ props = at "properties" schema+ at "$ref" (at "a1" props) `shouldBe` J.String "#/$defs/Box_Int"+ at "$ref" (at "b1" props) `shouldBe` J.String "#/$defs/Box_Int_2"+ at "$ref" (at "c1" props) `shouldBe` J.String "#/$defs/A_B_C"+ at "type" (at "Box_Int" defs) `shouldBe` J.String "integer"+ at "type" (at "Box_Int_2" defs) `shouldBe` J.String "string"+ at "type" (at "A_B_C" defs) `shouldBe` J.String "boolean" it "stores nothing, and asks for reasoning it can send back" $ do at "store" (body conversation) `shouldBe` J.Bool False