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

nanogpt-nanoproxy

v2.0.5

Published

Local OpenAI-compatible NanoGPT bridge with OpenCode npm plugin support, object/XML bridge protocols, native-first fallback, and standalone server mode.

Readme

NanoProxy

NanoProxy is a local OpenAI-compatible bridge for NanoGPT that makes tool-enabled clients work more reliably by rewriting tool-enabled requests into a stricter upstream bridge protocol and translating the model output back into standard OpenAI-style content, reasoning, and tool_calls for the client.

It supports both:

  • an OpenCode plugin
  • a standalone local server for OpenAI-compatible tools such as Roo Code, Kilo Code, Zed, Cline-style clients, and similar editors or agents

By default NanoProxy uses an object bridge that asks the upstream model to emit one structured JSON turn object inside normal content. NanoProxy incrementally parses that object and converts it back into native client fields. An XML bridge is also available as an alternative protocol when needed.

It also supports optional native-first fallback for selected models through BRIDGE_MODELS.

What NanoProxy Does

For tool-enabled requests, NanoProxy:

  1. rewrites the upstream request into the selected bridge protocol
  2. preserves streaming where possible for reasoning, visible content, and tool calls
  3. incrementally parses the bridged model output
  4. converts it back into normal OpenAI-style response fields
  5. retries once for the specific invalid-empty bridged-turn case

Requests without tools pass through normally.

Bridge Protocols

NanoProxy supports two bridge protocols for tool-enabled requests.

Object bridge

This is the current default.

NanoProxy asks the model to return one JSON turn object shaped like this:

{
  "v": 1,
  "mode": "tool",
  "message": "I will inspect the relevant files now.",
  "tool_calls": [
    {
      "name": "read",
      "arguments": {
        "path": "src/index.js"
      }
    }
  ]
}

Field meaning:

  • v: protocol version
  • mode: tool, final, or clarify
  • message: user-visible assistant text
  • tool_calls: tool requests when mode is tool

When the provider exposes reasoning separately, NanoProxy passes that through separately as reasoning content.

XML bridge

The XML bridge is also available as an alternative protocol:

$env:BRIDGE_PROTOCOL = "xml"
node server.js

In XML mode, NanoProxy asks the model to emit tool actions in a narrow XML format inside normal content.

Example:

<open>I will inspect the relevant files now.</open>
<read>
  <path>src/index.js</path>
</read>

How it works:

  • <open>...</open> carries visible user-facing text
  • tool calls are emitted as XML tags named after the tool
  • tool arguments are passed as child tags inside the tool tag
  • NanoProxy parses those XML tool calls incrementally and converts them back into standard OpenAI-style tool_calls
  • when batching is allowed, multiple tool tags can appear in the same response

BRIDGE_PROTOCOL

BRIDGE_PROTOCOL selects which bridge protocol NanoProxy uses after it decides to bridge a tool-enabled request.

  • not set: use object
  • object: use the object bridge
  • xml: use the XML bridge

Examples:

$env:BRIDGE_PROTOCOL = "object"
opencode
$env:BRIDGE_PROTOCOL = "xml"
node server.js
BRIDGE_PROTOCOL=object node server.js

Native-First Fallback and BRIDGE_MODELS

BRIDGE_MODELS decides which models bridge immediately and which models try native mode first.

  • not set: all tool-enabled requests bridge immediately
  • set to an empty string: all tool-enabled requests try native-first, then fall back to the selected bridge protocol if needed
  • set to a comma-separated list: matching models bridge immediately, other tool-enabled requests use native-first

Examples:

$env:BRIDGE_MODELS = ""
node server.js
$env:BRIDGE_MODELS = "glm-5,kimi-k2.5"
opencode
BRIDGE_MODELS="glm-5,kimi-k2.5" node server.js

Matching is substring-based against the model id.

OpenCode Plugin Setup

NanoProxy is set up to be publishable as an npm OpenCode plugin. Once the package is published, you will be able to install it by package name in your OpenCode config:

{
  "plugin": [
    "nanogpt-nanoproxy"
  ]
}

For local development or before the npm package is published, you can still load it from a local file path:

{
  "plugin": [
    "file:///path/to/NanoProxy/src/plugin.mjs"
  ]
}

Windows example:

{
  "plugin": [
    "file:///C:/Users/you/path/to/NanoProxy/src/plugin.mjs"
  ]
}

Then restart OpenCode.

Plugin logging

Plugin logging is off by default.

Enable the structured session log for one run:

$env:NANOPROXY_DEBUG = "1"
opencode

Enable raw request and response artifacts too:

$env:NANOPROXY_DEBUG = "1"
$env:NANOPROXY_RAW_LOGS = "1"
opencode

Optional override:

  • NANOPROXY_LOG_DIR for the plugin log directory

Default plugin log locations:

  • session logs: system temp under nanoproxy-plugin-logs
  • raw artifacts: system temp under nanoproxy-plugin-logs/raw when raw logging is enabled

If you installed the OpenCode plugin from npm, create a .debug-logging file in the OpenCode workspace root to enable plugin debug logging. Plugin logs still go to the temp folder under nanoproxy-plugin-logs.

Standalone Server Setup

Start the server:

node server.js

Default address:

http://127.0.0.1:8787

Environment variables:

UPSTREAM_BASE_URL=https://nano-gpt.com/api/v1
PROXY_HOST=127.0.0.1
PROXY_PORT=8787
BRIDGE_PROTOCOL=object
BRIDGE_MODELS="glm-5,kimi-k2.5"
node server.js

Server logging

Server logging is off by default.

Enable for one run:

$env:NANO_PROXY_DEBUG = "1"
node server.js

Or toggle persistently on Windows:

./toggle-debug.ps1

Server logs are written to Logs/ as one structured session log per server run.

Health check

curl http://127.0.0.1:8787/health

Example response:

{
  "ok": true,
  "mode": "object-bridge",
  "port": 8787,
  "upstream": "https://nano-gpt.com/api/v1",
  "debugLogs": false
}

When debug logs are enabled, the response also includes logDir.

Docker

NanoProxy server mode works in Docker.

Build and run:

docker build -t nanoproxy .
docker run --rm -p 8787:8787 nanoproxy

Or with Compose:

docker compose up --build

Compose uses the same environment model as the server, so you can add values like BRIDGE_PROTOCOL, BRIDGE_MODELS, or NANO_PROXY_DEBUG there when needed.

Logging Summary

Plugin mode

  • off by default
  • enabled by NANOPROXY_DEBUG=1|true or .debug-logging
  • raw artifacts additionally enabled by NANOPROXY_RAW_LOGS=1|true
  • logs go to the temp folder under nanoproxy-plugin-logs
  • one structured session log per plugin run

Server mode

  • off by default
  • enabled by NANO_PROXY_DEBUG=1|true or .debug-logging
  • logs go to Logs/
  • one structured session log per server run

Reliability Rules

Key behavior:

  • bridge activates only for tool-enabled requests
  • requests without tools pass through unchanged
  • object bridge is the default and the XML bridge remains available as an alternative protocol
  • bridged output is converted back into normal OpenAI-style response fields
  • invalid empty bridged turns are treated as protocol failures, not silent successes
  • NanoProxy performs one retry for the specific invalid-empty bridged-turn case: no visible content and no tool call
  • native-first passthrough is accepted only when the upstream response already looks structurally valid
  • idle bridged SSE streams send keepalive comment frames so clients do not time out as quickly

Repo Structure

NanoProxy/
|-- Dockerfile
|-- docker-compose.yml
|-- package.json
|-- README.md
|-- selftest.js
|-- server.js
|-- src/
|   |-- core.js
|   |-- object_bridge.js
|   `-- plugin.mjs
`-- toggle-debug.ps1

Verification

node --check src/core.js
node --check src/object_bridge.js
node --check src/plugin.mjs
node --check server.js
node selftest.js

Or:

npm run check