bun:yolo turns named Noul (yes/no), Choice and Score answers into JavaScript primitives. bun:Yolo resolves to the same module. Bun validates question types, answer names, choice keys and numeric bounds natively before returning a value.
import Yolo, { code, noul } from "bun:yolo";
const provider = code(request => ({
model: "public-access-rule",
answers: {
answer: { type: "noul", noul: (request.state as { visibility: string }).visibility === "public" ? 1 : 0 },
},
usage: null,
}));
if (await Yolo({ visibility: "public" }, noul("Is this resource public?"), { provider })) {
console.log("read allowed");
}
The result is a primitive boolean. A Noul becomes true only when its probability is greater than threshold, which defaults to 0.5. Use inspect when the probability itself matters. A judgment does not authorize side effects on its own: keep deterministic access rules in application code.
Named batches
import { decide, noul, choice, score, type Provider } from "bun:yolo";
export async function decideSources(provider: Provider) {
return await decide(
{
state: { query: "How does Bun.Video resize frames?", passage: "Bun.Video provides transformed frames." },
questions: {
relevant: noul("Does `passage` help answer `query`?"),
route: choice("Which public source fits `query`?", {
docs: "API documentation",
graph: "Relationships between source symbols",
none: "Neither source fits",
}),
evidence: score("How much support does `passage` provide for `query`?", [
"No supporting information",
"Information about the API, without the requested details",
"Information directly answering the requested details",
]),
},
},
{ provider, timeout: 10000, maxRetries: 0 },
);
}
// relevant: boolean; route: "docs" | "graph" | "none"; evidence: number in 0..2
All questions for one state share one provider request. Omitting provider selects remote(). The code provider above is deterministic; it demonstrates the protocol without performing a language judgment.
Limits:
- A batch contains 1–64 questions.
- A Choice has 2–255 named options.
- A Score has 2–10 ordered criteria and may return a fractional value between zero and the final index.
- Request and response JSON are each limited to 1 MiB.
- Model names must contain a non-whitespace character and fit within 256 UTF-8 bytes.
Unknown answer names, choice keys, wrong legends and numbers outside their range throw.
inspect(request, options) returns the validated { model, answers, usage } response. systemOne is an alias of inspect. ask(state, question, options) answers a single question. value(answer, question, threshold?) validates one answer and returns its primitive.
Providers
A Provider owns its transport, credentials and model. code(evaluate) adapts a synchronous or asynchronous callback to this contract. The callback returns the raw named response; Bun still validates the request, answer distributions and primitive conversion. Keep provider credentials on the server.
remote({ baseURL?, model?, client? }) uses native HTTP by default:
| Setting | Resolution order |
|---|---|
| API key | TYPESAFE_API_KEY |
| Endpoint | baseURL, then TYPESAFE_BASE_URL, then https://api.typesafe.ai |
| Model | the request's model, the provider's model, TYPESAFE_DEFAULT_MODEL, then jev-latest |
Requests use the /v1/systemone path. Endpoints require HTTPS; plain HTTP is accepted only for loopback addresses. URL credentials, query strings, fragments and redirects are rejected.
Supplying client delegates transport and retries to its systemOne method. Configure the endpoint on that client; baseURL cannot be combined with client. Native HTTP retries status codes 408, 429 and 5xx within maxRetries and the operation deadline. Authentication failures reject without retrying. Response bodies are bounded while streaming and must contain valid UTF-8 JSON.
This interface returns structured decisions, not generated text. See typed decision boundaries for confidence, abstention and the Python SDK.
Timeouts and cancellation
timeout bounds the whole operation, including serialization and pending retries, to 1–120000 ms (default 10000). Synchronous callbacks cannot be interrupted; their result rejects once control returns after the deadline. maxRetries is an integer from 0 to 3, default 0. Providers receive the deadline, retry limit and cancellation signal. An AbortSignal cancels the request and settles the caller even when a custom provider does not complete.
Local models
local({ context, model, maxTokens? }) accepts a loaded bun-llama context. The caller selects the GGUF model file and owns the context and model lifetime. No weights are downloaded or bundled.
The adapter requests strict JSON at temperature zero, caps generation at 1–4096 tokens (default 1024), and sends every answer through the same native validator. Markdown, explanatory text and responses outside the schema are rejected. Local adapters sharing a context accept one active request at a time; after cancellation or timeout, the context remains busy until its complete call settles. Token usage is null because the context does not report exact token counts. Local probabilities are raw model outputs and are not calibrated.
Optional providers require their credentials, native library or model to be available. Validation and code providers work without them.