laya-php
★ 110marcreichel/laya-php
Laravel-ready PHP client for Laya, the open System One model, so a typed decision is a PHP enum rather than a parsed sentence. Self-hosted, no Jev key.
SwiftPM client whose behaviour follows the official JavaScript SDK.
View on GitHub →Hands-on review
A small, well-shaped Swift client for Jev. It has no CI, and it will not compile on the server platform its own README recommends.
Good for
Watch out for
Tested Sep 20, 2026 at 4195213 · swift:6.1-noble in Docker with --network none; built and tested offline
How we reviewed this: we built and tested it ourselves in the swift:6.1-noble image with --network none, and read the request path line by line. We made no Jev calls.
A small Swift client for Jev. You declare your questions as typed values — noul, choice, score — pass any Encodable as the state, and get back a struct you defined. One POST /v1/systemone carries all of a decision’s questions, which is the shape Jev is designed around and which several clients in this directory get wrong.
The design is tidy. HTTPTransport is a protocol, so tests substitute a stub without touching the network; the retry policy is a value you can configure; and the auth header is deliberately not overridable, with a test asserting it.
Sources/TypeSafe/HTTP.swift, APISession.swift and TypeSafeClient.swift all use URLSession, URLRequest and HTTPURLResponse, and all three open with:
import Foundation
On Apple platforms that is enough. On Linux those types live in a separate module, and the repository contains no FoundationNetworking import anywhere — we grepped: zero occurrences. We built the published 4195213 in swift:6.1-noble, offline:
error: 'HTTPURLResponse' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it.
error: value of type 'HTTPURLResponse' (aka 'AnyObject') has no member 'statusCode'
--- error count ---
191
We then added the standard three-line guard to those same three files and built again:
Build complete! (5.90s)
Nine lines. What makes this worth writing down is not the bug, which every Swift package hits once, but that the README recommends calling the API “from a server you control” — and Linux is where that server almost certainly runs. There is no .github/ directory and no CI, so nothing has ever compiled this outside macOS.
RetryPolicy.default is maxRetries: 2 with retryTimeouts: true, and the client’s default timeout is .seconds(10). Sources/TypeSafe/APISession.swift:74:
} catch let error as TimeoutError {
logger.info("\(tag) timed out after \(formatMilliseconds(started.duration(to: .now)))")
if retriesLeft > 0, policy.retryTimeouts {
Nothing identifies the retry to the server as the same request. Searching the sources for an idempotency key or nonce returns two hits, and both are reading x-typesafe-request-id off a response — nothing is ever sent.
So a decision that takes longer than ten seconds is sent three times. The server answers all three and bills all three; the caller gets a TimeoutError and no answer. Ten seconds is not a generous budget for a model that evaluates a dozen questions over a long state, which makes this the default rather than the edge case. Retrying a connection failure is safe; retrying a timeout is not, because the first request may well have completed.
The decoder has no optionals anywhere. Sources/TypeSafe/Result.swift:11:
public struct SystemOneResult<Answers: Decodable & Sendable>: Decodable, Sendable {
public var model: String
public var answers: Answers
public var usage: Usage
}
Usage.inputTokens and outputTokens are plain Int; ModelCard.releaseDate is a plain String; a choice answer’s probabilities and a score answer’s legend are required dictionaries. Swift’s synthesised Decodable throws on any one of them being absent or a different type.
Unknown keys at the top level are tolerated, which is the right call and clearly deliberate. But the day the service adds a value to an existing enum, every deployed copy of this SDK throws — after the request has been made and paid for. There is also an undocumented asymmetry in the score question: the request encodes criteria as an array of level descriptions (Questions.swift:180), and the answer requires a legend object back (Questions.swift:157).
Sources/TypeSafe/HTTP.swift:43 hard-codes what it reports as your toolchain:
private let swiftVersion = "6.0"
We compiled with 6.1.3; the header still says swift/6.0. It is only telemetry, but it is telemetry that is wrong by construction.
Headers you set in Configuration(defaultHeaders:) are merged before the SDK’s own, and later wins (APISession.swift:120), so User-Agent and Accept are silently discarded along with Authorization. Locking the auth header is intentional; locking the other two is probably not, and neither is documented. And debug logging prints the full request body (APISession.swift:131) while redaction (Logging.swift:36) covers headers only — turn it on and your state goes to the log.
MIT, 20 commits, one contributor, no CI. The repository was created and pushed within about five minutes, which fits: this is a well-shaped first draft that has never been run anywhere but its author’s machine.
Once the conditional imports land it is a reasonable Swift client, and the typed-question API is nicer to use than hand-rolling the JSON. Until then it is Apple-platforms-only in practice, whatever the README says. We’ve reported the build failure, the timeout retry and the strict decoding.
For the same job in other languages, see jev-repl and the .NET SDK.
See how it compares with other tools in Best Jev tools, tested hands-on.
Review updated Sep 20, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.
marcreichel/laya-php
Laravel-ready PHP client for Laya, the open System One model, so a typed decision is a PHP enum rather than a parsed sentence. Self-hosted, no Jev key.
spring-ai-community/spring-ai-typesafe
Java client for the System One API on Spring RestClient, plus Spring AI integrations that use it as a judge, a guardrail, a RAG post-processor and a tool index.
obie/ruby_decision_model
Ruby gem with one client for decision models behind several providers: TypeSafe's Jev, OpenRouter (the default), OpenAI, Cloudflare Clef, Perplexity and any /v1/systemone server.
New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.
Powered by Buttondown. See our privacy policy.