jev-to-laya-proxy

Point your TypeSafe code at your own machine.

jev-to-laya-proxy accepts Jev API requests and answers them with a Laya model running locally. Same questions, same response shape, no API key.

$ ./jev-proxy --log:8787
  1. client→proxyPOST /v1/systemone "model":"jev-latest" "state":"Help! My payouts have been failing for 3 days."
  2. proxy→backendPOST 127.0.0.1:8770/api/predict "model":null (Laya picks the model)
  3. backend→proxy200 answers + routing, action, latency_ms, device
  4. proxy→client200 381ms {model, answers, usage} Laya extras removed
department choice
billing81.3%
technical9.8%
sales8.9%
is_urgent noul
yes74.2%

What it does

TypeSafe's Jev API takes some text (the state) and a set of typed questions, then returns an answer with a probability for each one. Laya uses almost the same format, but it runs on your laptop.

The proxy sits between them. It checks each request the way Jev would, renames the model to one Laya knows, forwards the call, and removes the fields Jev doesn't return. Code written for Jev, including the official SDKs, keeps working when you change the base URL.

Three question types

noul is a yes-or-no question. It returns the probability that the answer is yes.

choice picks one option from a list and returns a probability for every option.

score places the text on an ordered rubric of 2 to 10 levels. It returns a weighted score and the probability of each level.

Your side speaks Jev

POST /v1/systemone, GET /v1/models, Bearer auth, and the 401, 422 and 529 error codes.

The backend can be anything Jev-like

It's Laya by default. Switching to real TypeSafe, or another server, is a change to config.json.

Quick start

  1. Start Laya locally. It should answer on port 8770.

    curl http://127.0.0.1:8770/api/health
  2. Download the proxy for your platform, extract it, and run it with logging on.

    tar -xzf jev-proxy-darwin-arm64.tar.gz
    xattr -d com.apple.quarantine jev-proxy-darwin-arm64   # macOS only
    ./jev-proxy-darwin-arm64 --log
  3. Send a Jev request to port 8787.

    curl localhost:8787/v1/systemone \
      -H 'Content-Type: application/json' \
      -d '{
        "state": "Help! My payouts have been failing for 3 days.",
        "model": "jev-latest",
        "questions": {
          "is_urgent": { "type": "noul", "instructions": "Does this convey urgency?" }
        }
      }'
  4. Or point a TypeSafe SDK at it. Any API key works unless you set one in the config.

    const client = new TypeSafeClient({ baseURL: "http://localhost:8787", apiKey: "local" });

Download

Each binary includes the Bun runtime, so there's nothing else to install. These links always point to the latest release.

To run from source instead, use bun proxy.ts --log in a clone of the repo.

Configure

Settings live in config.json. The binary has a copy built in, and a config.json in the folder you run from overrides it. Use ${VAR} in any value to read it from the environment, so keys stay out of the file.

Environment variables: PORT, BACKEND, CONFIG, and LOG=1, which does the same as --log.

Every response carries an x-served-by: jev-proxy header, so you can confirm the proxy answered.

{
  "backend": "laya",
  "backends": {
    "laya": {
      "url": "http://127.0.0.1:8770",
      "predictPath": "/api/predict",
      "modelMap": {
        "jev-latest": null,
        "laya-english": "english"
      }
    },
    "typesafe": {
      "url": "https://api.typesafe.ai",
      "predictPath": "/v1/systemone",
      "headers": {
        "Authorization": "Bearer ${TYPESAFE_API_KEY}"
      }
    }
  }
}

Model names

Send this modelLaya uses
jev-latest, jev-preview, or any unknown nameIts own choice, based on the text's language
laya-englishenglish
laya-multilingualmultilingual
laya-typedtyped-decisions