packages feed

agentic-openai 0.2.0.3 → 0.2.0.4

raw patch · 5 files changed

+23/−19 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Changelog for agentic-openai +## 0.2.0.4 - 2026-10-06++* Follows agentic's record field changes; no API change.+ ## 0.2.0.3 - 2026-10-06  * Follows agentic's renames: `endpoint` is `Text`.
agentic-openai.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               agentic-openai-version:            0.2.0.3+version:            0.2.0.4 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.
src/Agentic/OpenAI.hs view
@@ -141,15 +141,15 @@   A.Object $     [("model", A.String cfg.model)]       <> maybe [] (\s -> [("instructions", A.String s)]) cfg.system-      <> [("tools", A.Array (map tool (tools c))) | not (null (tools c))]-      <> [ ("input", A.Array (task : concatMap exchange (history c)))+      <> [("tools", A.Array (map tool c.tools)) | not (null c.tools)]+      <> [ ("input", A.Array (task : concatMap exchange c.history))          , ( "text"            , A.Object                [ ( "format"                  , A.Object                      [ ("type", A.String "json_schema")-                     , ("name", A.String (schemaName (outputSchema c)))-                     , ("schema", objectSchema (outputSchema c))+                     , ("name", A.String (schemaName c.outputSchema))+                     , ("schema", objectSchema c.outputSchema)                      , ("strict", A.Bool True)                      ]                  )@@ -161,16 +161,16 @@       <> maybe [] (\e -> [("reasoning", A.Object [("effort", A.String (effortName e))])]) cfg.effort       <> maybe [] (\n -> [("max_output_tokens", A.Integer (toInteger n))]) cfg.maxTokens   where-    task = message "user" (instructionText (instruction c) <> inputText)-    inputText = case input c of+    task = message "user" (c.instruction.text <> inputText)+    inputText = case c.input of       A.Null -> ""       s -> "\n\nInput:\n" <> A.renderJson s     tool spec =       A.Object         [ ("type", A.String "function")-        , ("name", A.String (specName spec))-        , ("description", A.String (specDescription spec))-        , ("parameters", objectSchema (specInput spec))+        , ("name", A.String spec.name)+        , ("description", A.String spec.description)+        , ("parameters", objectSchema spec.input)         , ("strict", A.Bool True)         ]     -- A turn's raw value is its list of output items, which go back as input.@@ -235,13 +235,13 @@     -- A reply that isn't JSON goes back to the core as text; the output     -- contract then rejects it and the model gets another go.     final text = case decodeJson text of-      Just v -> unwrap (outputSchema c) v+      Just v -> unwrap c.outputSchema v       Nothing -> A.String text     json t = maybe (A.String t) id (decodeJson t)     decodeJson t = fromAeson <$> J.decode (TL.encodeUtf8 (TL.fromStrict t))     unwrapInput name v = maybe v (`unwrap` v) (inputSchema name)     inputSchema :: Text -> Maybe Schema-    inputSchema name = case [specInput s | s <- tools c, specName s == name] of+    inputSchema name = case [s.input | s <- c.tools, s.name == name] of       s : _ -> Just s       [] -> Nothing 
test-live/Live.hs view
@@ -15,9 +15,9 @@   deriving (Generic, Show, Contract)  data BetterJoke-  = DadJoke {setup' :: Text, punchline' :: Text}+  = DadJoke {setup :: Text, punchline :: Text}   | OneLiner {line :: Text}-  | KnockKnock {whosThere :: Text, punchline' :: Text}+  | KnockKnock {whosThere :: Text, punchline :: Text}   deriving (Generic, Show, Contract)  data Groan = Mild | Solid | Unbearable
test/Spec.hs view
@@ -29,8 +29,8 @@     , instruction = "Suggest 3 dinosaurs"     , input = Null     , inputSchema = schemaOf SNull-    , tools = [ToolSpec "search" "Search the fossil database" (codecSchema (contract @Text))]-    , outputSchema = codecSchema (contract @[Text])+    , tools = [ToolSpec "search" "Search the fossil database" ((contract @Text).schema)]+    , outputSchema = (contract @[Text]).schema     , history = []     } @@ -57,7 +57,7 @@         )    it "names the schema after its type, and shares repeated types through $defs" $ do-    let format = at "format" (at "text" (body conversation {outputSchema = codecSchema (contract @Board)}))+    let format = at "format" (at "text" (body conversation {outputSchema = (contract @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\"}")@@ -90,11 +90,11 @@         )    it "reads function calls, parsing and unwrapping their arguments" $-    fmap action (decoded (fromJust (J.decode "{\"status\":\"completed\",\"output\":[{\"type\":\"reasoning\"},{\"type\":\"function_call\",\"call_id\":\"c1\",\"name\":\"search\",\"arguments\":\"{\\\"value\\\":\\\"rex\\\"}\"}]}")))+    fmap (.action) (decoded (fromJust (J.decode "{\"status\":\"completed\",\"output\":[{\"type\":\"reasoning\"},{\"type\":\"function_call\",\"call_id\":\"c1\",\"name\":\"search\",\"arguments\":\"{\\\"value\\\":\\\"rex\\\"}\"}]}")))       `shouldBe` Right (CallTools [ToolCall "c1" "search" (String "rex")])    it "reads a final answer from the message text" $-    fmap action (decoded (fromJust (J.decode "{\"status\":\"completed\",\"output\":[{\"type\":\"message\",\"content\":[{\"type\":\"output_text\",\"text\":\"{\\\"value\\\":[\\\"Stegosaurus\\\"]}\"}]}]}")))+    fmap (.action) (decoded (fromJust (J.decode "{\"status\":\"completed\",\"output\":[{\"type\":\"message\",\"content\":[{\"type\":\"output_text\",\"text\":\"{\\\"value\\\":[\\\"Stegosaurus\\\"]}\"}]}]}")))       `shouldBe` Right (Respond (Array [String "Stegosaurus"]))    it "reports refusals and truncation as errors" $ do