@spikefrost/decide
v0.1.0
Published
Typed decisions (choice / score / boolean) for Spike Apps through the platform relay. Zero dependencies.
Maintainers
Readme
@spikefrost/decide
Typed decisions for Spike Apps: evaluate a state against choice, score,
and boolean questions and get typed answers with probabilities back, in
milliseconds, through the platform relay. Same tenant key, budget gate, and
wallet as an LLM call. The App never holds a provider key.
import { decider, choice, score, boolean, isLikely } from "@spikefrost/decide";
const d = decider.fromEnv(env); // SPIKE_RELAY_URL + SPIKE_TENANT_API_KEY are injected at deploy
const r = await d.evaluate({
state: { subject: ticket.subject, body: ticket.body },
questions: {
route: choice("Route this ticket.", { billing: "charges", shipping: "delivery", technical: "bugs" }),
urgency: score("How urgent is this?", ["low", "medium", "high"]),
refund: boolean("Is a refund being requested?"),
},
});
r.answers.route.choice; // "billing" | "shipping" | "technical"
r.answers.urgency.score; // 0..2, probability-weighted
isLikely(r.answers.refund, 0.8); // P(true) >= 0.8Default model is typesafe-ai/jev-1.13.0. Run sf models for the current
decision models and prices.
Rules
- Server-side only. Never ship the tenant key to a browser.
- A
DecideErrorwithisPaymentRequiredmeans balance or budget. Surface it; never retry-loop it. - Retries happen only on 429 and 529, at most
maxRetries(default 2). - One request evaluates ONE state. For many items use
evaluateManyorcreateCoalescer(room Durable Objects), which pack many items into one request with independent answers. - State leaves the platform to the decision provider. Send what the judgment needs, not the whole record.
Batching in a room Durable Object
const mod = createCoalescer(d, {
windowMs: 75,
questions: () => ({ toxic: boolean("Is `item`.text harassment toward another player?") }),
});
// per chat line, fire and forget the outcome into game logic
mod.submit({ text }).then(a => { if (isLikely(a.toxic, 0.9)) mute(player); }).catch(() => {/* degrade to rules */});