com.softinio.verdict4s
Members list
Packages
Grouped members
Errors
Failures a verdict4s call can produce.
Failures a verdict4s call can produce.
Lives in the effect-free core so that callers can pattern match on it without taking a dependency on cats-effect or http4s.
Attributes
- Companion
- object
- Supertypes
- Known subtypes
Questions
A set of questions asked together, answered at exactly the right types.
A set of questions asked together, answered at exactly the right types.
One request carrying several questions is both cheaper and faster than one request each, and it is the shape the service is designed around. Ask keeps that batching while preserving each question's own answer type:
val (urgent, dept, mood) = client.ask(
Ask(
Question.noul("Does this convey urgency?"),
Question.choice[Dept]("Which team should handle this?"),
Question.score("How frustrated?", Seq("Calm", "Cross", "Livid"))
),
state
)
urgent is a NoulAnswer, dept a ChoiceAnswer[Dept] and mood a ScoreAnswer -- destructured positionally, with no casts and no lookups by string. The map-based algebra.Evaluation remains available for cases where the questions are not known statically.
Question keys are generated positionally, so callers never name them. Use withKeys if you need them to match something else.
Attributes
- Companion
- object
- Supertypes
Configuration
Where a retry delay's randomness comes from.
Where a retry delay's randomness comes from.
A two-method trait rather than a direct call to a random source, for two reasons. Tests get a fully deterministic schedule from Jitter.constant without a mocking library. And the obvious alternatives are both worse here: cats.effect.std.Random is only transitively on the classpath, and deriving randomness from Temporal.monotonic yields a constant on Scala.js, where the clock is millisecond-granular.
This lives in the client, not in algebra, because drawing a sample is an effect and the core must stay effect-free.
Attributes
- Companion
- object
- Supertypes
Reading configuration from the environment. JVM only.
Reading configuration from the environment. JVM only.
A separate object rather than methods on Verdict4s, and not by preference: a Scala object cannot be split across src/ and src-jvm/, so adding these there would force jev and openAI to be duplicated into both platform directories — exactly the drift that keeping one signature on both platforms is meant to prevent.
Scala.js has no environment to read, so this simply does not exist there. The JVM artifact having a slightly larger surface than the JS one is normal and does not affect Verdict4s.
Variable names match each vendor's official SDKs, so a project can share them:
| Variable | Meaning |
|---|---|
VERDICT4S_VENDOR |
jev (the default) or openai, for default |
TYPESAFE_API_KEY |
Jev's API key |
TYPESAFE_BASE_URL |
Jev's address |
TYPESAFE_DEFAULT_MODEL |
Jev's default model |
OPENAI_API_KEY |
OpenAI's API key |
OPENAI_BASE_URL |
OpenAI's address, including /v1 |
Attributes
- Supertypes
- Self type
-
Verdict4sEnv.type
Client
A client for TypeSafe AI's Jev: the shared surface, plus ModelCatalog.
A client for TypeSafe AI's Jev: the shared surface, plus ModelCatalog.
Built with Verdict4sClient.jev. Its copy methods return a JevClient, so withConfig never loses the model catalog.
Attributes
- Supertypes
A client for OpenAI Decisions: the shared surface, plus SafetyIdentity.
A client for OpenAI Decisions: the shared surface, plus SafetyIdentity.
Built with Verdict4sClient.openAI. Its copy methods return an OpenAIClient, so withConfig never loses the safety identifier.
Attributes
- Supertypes
A vendor that accepts an identifier for your end user, to help it detect abuse. OpenAI Decisions does, as safety_identifier.
A vendor that accepts an identifier for your end user, to help it detect abuse. OpenAI Decisions does, as safety_identifier.
Attributes
- Supertypes
- Known subtypes
-
class OpenAIClient[F]
Batteries-included entry point.
Batteries-included entry point.
Picks a sensible transport for whichever platform you are on — Ember on the JVM, the browser and Node Fetch API on Scala.js — so getting a working client is a one-liner, for either vendor:
Verdict4s.jev[IO](typesafeKey).use { client =>
client.ask(Ask(Question.noul("Is this urgent?")), ticket)
}
Verdict4s.openAI[IO](openAIKey).use { client =>
client.ask(Ask(Question.noul("Is this urgent?")), ticket)
}
If you already have an http4s Client[F], or want a backend other than the default, depend on verdict4s-client and construct a Verdict4sClient directly.
Attributes
- Supertypes
- Self type
-
Verdict4s.type
A client for a decision API: Jev, OpenAI Decisions, or any other Vendor.
A client for a decision API: Jev, OpenAI Decisions, or any other Vendor.
Code written against this trait works with every vendor. The questions, Ask and the typed answers are the same whichever one answers them:
def triage[F[_]](
client: Verdict4sClient[F]
): F[(NoulAnswer, ChoiceAnswer[Dept])] =
client.ask(
Ask(
Question.noul("Does this convey urgency?"),
Question.choice[Dept]("Which team should handle this?")
),
"Help! My payouts have been failing for 3 days."
)
triage(Verdict4sClient.jev[IO](httpClient, typesafeKey))
triage(Verdict4sClient.openAI[IO](httpClient, openAIKey))
What only one vendor offers is a separate capability trait, mixed into that vendor's client: ModelCatalog on JevClient, SafetyIdentity on OpenAIClient. Ask for exactly what you use, and the compiler stops a call the chosen vendor cannot serve:
def report[F[_]](using c: Verdict4sClient[F] & ModelCatalog[F]) = c.models
Takes an http4s Client[F] rather than building one. That single decision buys every backend and every platform without this library owning any of them — Ember, Fetch, Blaze, Netty, the JDK client — and it is why the test suite needs no network: Client.fromHttpApp serves routes in memory, so the same tests run on the JVM and on Node.
Retries are on by default, matching the official SDKs; see algebra.RetryPolicy to tune or disable them.
Attributes
- Companion
- object
- Supertypes
- Known subtypes
-
class JevClient[F]class OpenAIClient[F]
Constructing a client over a transport you supply.
Constructing a client over a transport you supply.
Attributes
- Companion
- trait
- Supertypes
- Self type
-
Verdict4sClient.type
Optional sugar for the call site.
Optional sugar for the call site.
The documented form is client.ask(questions, state), which needs nothing in implicit scope and infers F from the client. This import adds a reading-order alternative for those who prefer it:
import com.softinio.verdict4s.syntax.*
given Verdict4sClient[IO] = client
val (urgent, dept) = Ask(q1, q2).run("payouts failing")
run needs the client as a given for F to be inferable, which is an unusual idiom; runWith is the same thing with the client passed explicitly.
Attributes
- Supertypes
- Self type
-
syntax.type
Protocol
How to speak to one vendor's decision API.
How to speak to one vendor's decision API.
Jev and OpenAI Decisions answer the same three kinds of question with the same kinds of answer, and differ only in how they spell them on the wire. The questions, Ask and the typed answers are therefore shared, and a Vendor is everything that is not: where to send a request, how to encode it, how to read the reply, and which requests the vendor accepts.
A value rather than a typeclass, so that the vendor can be chosen at runtime, from configuration, without a type parameter on every signature.
It is also the way to drive a vendor with no effect system at all. Render a request, send it with whatever HTTP client you already have, and parse the reply back into typed answers:
val vendor = Vendor.OpenAI
val body = vendor.renderAsk(ask, state) // Either[Verdict4sError, String]
val text = myHttpClient.post(
vendor.evaluateUrl,
vendor.headers(key),
body
) // your code
val answers = vendor.parseAsk(ask, text)
Attributes
- Companion
- object
- Supertypes
- Known subtypes
-
object JevVendorclass OpenAIVendor
Type members
Classlikes
The cases of Verdict4sError, and a constructor for API errors built from a raw response.
The cases of Verdict4sError, and a constructor for API errors built from a raw response.
Attributes
- Companion
- class
- Supertypes
- Self type
-
Verdict4sError.type