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

@npv12/opencode-jev-router

v0.1.0

Published

OpenCode V2 plugin that uses Jev to pick reasoning effort and worker models per prompt

Readme

@npv12/opencode-jev-router

An OpenCode V2 plugin that asks Jev how much reasoning effort the agent needs, and which model a subagent should run on, so cheap work stays cheap and hard work gets the budget it needs.

What it does

  • Main session: never changes the model. On each user prompt, and every 30 agent steps, Jev picks the reasoning effort (variant) for the model already in play, and the session switches to the same provider and model with the new variant. Upgrades always apply; downgrades apply unless recalc.allowDowngrade is false.
  • Workers: a session with a parent routes itself. Jev picks both the model and the effort from the models whitelist. Workers whose agent has a pinned model are skipped entirely.
  • Failures count: failed steps and tool calls since the last check are fed back to Jev, which pushes effort up when the current one is not working.

Install

Add the plugin to your opencode.jsonc:

{
  "plugins": [
    {
      "package": "@npv12/opencode-jev-router",
      "options": {
        "models": {
          "opencode-go/deepseek-v4.1-flash": "Cheapest tier. Routine edits, lookups, one-liners, narrow questions.",
          "opencode-go/glm-5.3-flash": "Cheap, with more thinking than deepseek. Small multi-file work, straightforward debugging, ordinary explanations.",
          "openai/gpt-6-sol": "Expensive tier, only for heavy work: code review, larger refactors, cross-file reasoning.",
          "anthropic/claude-opus-5-5": "Most expensive tier, last resort: architecture, subtle bugs, work the cheaper tiers are unlikely to handle."
        },
        "default": "opencode-go/deepseek-v4.1-flash",
        "decider": "openrouter/typesafe/jev-1.14"
      }
    }
  ]
}

and restart OpenCode.

Options

| Option | Default | Description | | --- | --- | --- | | models | {} | provider/model to a description Jev reads when choosing a worker model. Without it, workers keep their inherited model. | | default | none | Model a worker falls back to when Jev does not answer. | | decider | none | opencode/jev-<version> (OpenCode Console) or openrouter/typesafe/jev-<version> (OpenRouter). | | recalc.steps | 30 | Agent steps between effort checks within one turn. | | recalc.allowDowngrade | true | Whether a check may lower the effort. |

Decider

The plugin uses the credential you already connected for the decider's provider in OpenCode.

A pinned decider is a data policy, not a preference: it is used alone, with no fallback, so a failure never falls through to an endpoint that may train on prompt data. Without a pinned decider, the OpenCode Console is tried first and OpenRouter second, using whichever credentials are available. If no credential is found, routing is disabled and a warning is logged.

How effort is decided

Both triggers send the same question and the same state shape. The question is:

How much reasoning effort should the agent use now? Repeated failures mean the current effort is not working, so choose a higher one.

The second sentence is load-bearing. Without it Jev keeps low on a trivial follow-up even after five failed steps. With it, the same state returns high.

State is ordered most decision-relevant first, so truncation at 8,000 characters drops only old context:

Request: <current prompt>                      (human-message trigger only)
Agent steps since the last check: N
Failed steps and tool calls since the last check: F
Recent failures:                               (when any)
- ...
Model: <name>
Current effort: <variant|unset>
Earlier requests:                              (every prior human message, oldest dropped first)
- ...

Step and failure counters reset on each check, so "since the last check" is literal.

Effort descriptions are relative to the ladder

Models expose different rungs: some offer three (low/high/max), others six (none/low/medium/high/xhigh/max). "Most requests" has to land on the second rung either way, so the descriptions are computed from the rungs actually offered rather than being fixed per name:

| Position | Description | | --- | --- | | first | Trivial only: yes/no answers, a single line or function to read, typo fixes, a single tiny edit. | | second | Ordinary work, and most requests belong here: writing or changing code, adding tests, small refactors, explanations, ordinary debugging. | | middle | Harder work: multi-file changes, non-obvious debugging, design decisions. | | second to last | Very hard: complex architecture, subtle concurrency, extended debugging after repeated failure. | | last | Genuinely hard: architecture and design decisions, subtle concurrency, multi-file refactors, deep debugging after repeated failure, cross-cutting migrations. |

Two-rung ladders map to trivial and ordinary. One-rung ladders have nothing to decide.

Fixed per-name hints scored 5/13 against a target distribution because low read as a reasonable choice for ordinary work. Relative banding scores 12/13 on the three-rung ladder and spreads sensibly on the six-rung one.

Measured gradient with the current wording:

| Failures since last check | Effort | | --- | --- | | 0 | low (0.88) | | 1 | medium (0.56) | | 2 | high (0.49) | | 4 | high (0.85) | | 6 | high (0.89) |

Answers on genuinely hard requests sit at 0.3 to 0.5 confidence, so the high/max boundary is noisy.

Loading from source

A config plugins entry pointing at a local path must be a directory containing index.ts:

{
  "plugins": [{ "package": "/absolute/path/to/opencode-jev-router/src", "options": {} }]
}

A .ts file is rejected, and a package root with a main is silently skipped. Relative paths resolve from the config file's directory.

Development

bun install
bun run check
bun run build

Releasing

Publish a GitHub release tagged vX.Y.Z. The workflow sets the version from the tag, typechecks, tests, builds, publishes to npm with provenance, and commits the version bump back to main.