npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/api-ai-decisions-jev

v1.1.1

Published

Jev decisions provider for molecule.dev — typed choice/score/yes-no answers from TypeSafe's hosted Jev System One API

Readme

@molecule/api-ai-decisions-jev

Jev decisions provider for molecule.dev — typed decisions from TypeSafe AI's hosted Jev "System One" model.

Jev answers choice, score and yes/no questions about text or JSON with a probability distribution instead of generated text. This bond calls POST https://api.typesafe.ai/v1/systemone with your TYPESAFE_API_KEY. The open-weights Laya server speaks the same protocol, so @molecule/api-ai-decisions-laya is a drop-in self-hosted swap.

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Quick Start

import { setProvider, requireProvider } from '@molecule/api-ai-decisions'
import { provider } from '@molecule/api-ai-decisions-jev'

setProvider(provider) // reads TYPESAFE_API_KEY on first use

const { answers } = await requireProvider().decide({
  state: { from: '[email protected]', body: 'Your app deleted my notes!!' },
  questions: {
    severity: {
      type: 'score',
      instructions: 'How severe is the problem?',
      criteria: ['cosmetic', 'annoying', 'blocking', 'data loss'],
    },
    churnRisk: { type: 'yesNo', instructions: 'The customer is likely to cancel.' },
  },
})
answers.severity.level // 3
answers.churnRisk.probability // 0.81

Type

provider

Installation

npm install @molecule/api-ai-decisions-jev @molecule/api-ai-decisions @molecule/api-secrets

API

Interfaces

JevConfig

Configuration for the Jev decisions provider.

interface JevConfig {
  /** TypeSafe API key. Defaults to the `TYPESAFE_API_KEY` env var (the name TypeSafe's own SDKs read). */
  apiKey?: string
  /**
   * Extra request headers, resolved before each call and merged over the
   * defaults — for a host whose auth expires or is not a bearer token (a Cloud
   * Run ID token, Modal proxy auth). Pair with `@molecule/api-model-hosting`:
   * `headers: () => hosting.authHeaders(endpoint.id)`.
   */
  headers?: () => Record<string, string> | Promise<Record<string, string>>
  /**
   * API base URL. Defaults to `TYPESAFE_BASE_URL`, then `https://api.typesafe.ai`.
   * Point it at a gateway that relays `/v1/systemone` (or at a `laya-serve`
   * host — same protocol) without changing code.
   */
  baseUrl?: string
  /** Default model id. Defaults to `'jev-latest'`. */
  model?: string
}

WireQuestion

One question as sent on the wire.

interface WireQuestion {
  type: 'choice' | 'score' | 'noul'
  instructions: string
  criteria?: Record<string, string> | string[]
}

WireAnswer

One answer as received on the wire (only the fields we read).

interface WireAnswer {
  type?: string
  choice?: string
  score?: number
  noul?: number
  probabilities?: Record<string, number>
}

WireResponse

The response body (only the fields we read).

interface WireResponse {
  model?: string
  answers?: Record<string, WireAnswer>
  usage?: { input_tokens?: number; output_tokens?: number }
}

PostOptions

Options for {@link postSystemOne}.

interface PostOptions {
  /** Full endpoint URL. */
  url: string
  /** Bearer token, if any. */
  apiKey?: string
  /** Extra headers resolved before the request (merged over the defaults). */
  headers?: () => Record<string, string> | Promise<Record<string, string>>
  /** Request body. */
  body: Record<string, unknown>
  /** Abort signal. */
  signal?: AbortSignal
  /** Label for error messages (`'Laya'`, `'Jev'`). */
  label: string
  /** Max retries on a retryable status (default 3). */
  maxRetries?: number
}

Functions

createProvider(config)

Creates a Jev decisions provider.

function createProvider(config?: JevConfig): AIDecisionsProvider
  • config — API key, base URL and default model.

Returns: An AIDecisionsProvider backed by TypeSafe's Jev API.

toWireQuestions(questions)

Converts the core's questions into wire questions (yesNo → noul).

function toWireQuestions(questions: Record<string, DecisionQuestion>): Record<string, WireQuestion>
  • questions — The questions keyed by id.

Returns: The wire questions object.

fromWireAnswer(id, question, wire, minConfidence)

Converts one wire answer into the core's answer for question.

function fromWireAnswer(
  id: string,
  question: DecisionQuestion,
  wire: WireAnswer | undefined,
  minConfidence?: number,
): DecisionAnswer
  • id — The question id (for error messages).
  • question — The question that was asked.
  • wire — The wire answer.
  • minConfidence — Optional low-confidence threshold.

Returns: The typed answer.

fromWireResponse(questions, body, minConfidence)

Converts a whole wire response into the core's result.

function fromWireResponse(questions: Q, body: WireResponse, minConfidence?: number): DecideResult<Q>
  • questions — The questions that were asked.
  • body — The parsed response body.
  • minConfidence — Optional low-confidence threshold.

Returns: The typed result.

postSystemOne(opts)

POSTs a /v1/systemone request with retry on 429/5xx-busy, honouring Retry-After. Throws an Error carrying status on a non-2xx response.

function postSystemOne(opts: PostOptions): Promise<WireResponse>
  • opts — Request options.

Returns: The parsed response body.

Constants

DEFAULT_JEV_URL

TypeSafe's API host.

const DEFAULT_JEV_URL: 'https://api.typesafe.ai'

DEFAULT_JEV_MODEL

TypeSafe's flagship model id.

const DEFAULT_JEV_MODEL: 'jev-latest'

provider

The provider implementation — lazy, so env vars are read on first use.

const provider: AIDecisionsProvider

aiDecisionsJevSecretDefinitions

Secret definitions required by the Jev decisions bond.

const aiDecisionsJevSecretDefinitions: SecretDefinition[]

Core Interface

Implements @molecule/api-ai-decisions interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setProvider } from '@molecule/api-ai-decisions'
import { provider } from '@molecule/api-ai-decisions-jev'

export function setupAiDecisionsJev(): void {
  setProvider(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-ai-decisions ^1.0.0
  • @molecule/api-secrets ^1.0.1

Environment Variables

  • TYPESAFE_API_KEY (required) — TypeSafe API key
    • Setup: Create an API key in your TypeSafe AI account; it is sent as a bearer token to the Jev API.
    • Get it here: https://docs.typesafe.ai/api
    • Example: ts-...

Runtime Dependencies

  • @molecule/api-ai-decisions

  • @molecule/api-secrets

  • Config: TYPESAFE_API_KEY (required — sent as Authorization: Bearer …), TYPESAFE_BASE_URL (optional; a gateway, or a laya-serve host), and createProvider({ model }) (default 'jev-latest', or pass model per call).

  • Limits (TypeSafe docs): up to 255 options per choice, 2–10 levels per score. 429 (rate limit) and 529 (overloaded) are retried up to 3 times with backoff; 401 and 422 throw immediately with the API's message and a status property.

  • English-first. TypeSafe describes English as Jev's primary training language; for other languages evaluate carefully or use Laya's multilingual checkpoint.

  • Your data leaves your servers (TypeSafe processes the state). For data that must stay in your environment, bond the Laya provider instead.

  • confidence in the answers is the probability of the reported answer, NOT Jev's own confidence field (see the core's remarks).

  • Hosted on rented compute? Pass headers: () => hosting.authHeaders(endpoint.id) (@molecule/api-model-hosting) when the host's auth expires or is not a bearer token — e.g. a Cloud Run ID token or Modal proxy auth. It runs before every request and is merged over the defaults.

  • Use the core's setProvider, not bond('ai-decisions', …) directly.

E2E Tests

Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • [ ] Each flow that makes a decision (routing, triage, moderation, a guardrail) runs it from the real UI, and the answer DRIVES what happens next (the item lands in the chosen queue, the badge shows, the action is blocked) — not just printed.
  • [ ] Both directions: a clearly-billing input routes to billing AND a clearly-technical one routes elsewhere. One label for every input is a broken integration.
  • [ ] A low-confidence answer takes the app's fallback path (human review, "unsure" state) instead of being acted on.
  • [ ] Provider errors (service down, bad key) show a visible, recoverable state — never a blank screen or an unhandled rejection.
  • [ ] The call runs server-side: no provider request or key in the browser's Network tab.