@lunaroute/pi-extension0.18.0
Pi extension for LunaRoute: login, model sync, request attribution, and first-class web tools.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
LunaRoute for Pi
Use LunaRoute from Pi in under a minute: log in, and every LunaRoute model shows up automatically — correctly configured and ready to use. No hand-editing model files, no copying API keys around. The hosted LunaRoute MCP server (image generation and more) is wired up for you too.
Why
- Zero-config models. LunaRoute's model catalog is synced into Pi
automatically — context windows, token limits, reasoning, and vision
capabilities all come through pre-mapped. Run
/modeland pick alunaroute/*model. Re-fetched on every refresh, so new models appear as soon as they ship — or run/lunaroute models-refreshto pull the catalog without restarting Pi. - First-class web search. When no other extension provides web search,
a real
web_searchPi tool is registered, backed by the hosted LunaRoute MCP server — collapsed rows, expandable sources, parallel calls. Aweb_fetchcompanion lights up automatically once the server offers one. - Login that doesn't leak keys. Browser-based login (PKCE) issues a fresh
lr_key and stores it in~/.pi/agent/auth.json— never in a models file. Prefer a key you already have? Paste it. - LunaRoute MCP built in. When you're logged in, the hosted LunaRoute MCP
server is auto-registered so tools like
generate_imageare callable from Pi. Nothing is written to your MCP config; registration lives only for the Pi process. - Attribution on every request. Each LunaRoute request carries a per-session agent + session id so traffic is traceable on the LunaRoute side.
- Per-model image sizing. Vision models are registered with the image resize
profile the LunaRoute catalog carries (
client_compat.pi.inputLimits), so Pi downscales attachments,readimages, and tool-result images before they enter history — keeping requests under the gateway's size cap. Requires Pi >= 0.87; the field is inert on older hosts. Without a catalog profile the extension applies a conservative default (2048x2048, 1 MiB), andmodelOverridesinmodels.jsoncan tune it per model. - System One decision models as classifier models. The LunaRoute catalog's
System One models (
capabilities.systemone) are registered as Pi classifier models, socodemodescripts and extensions can call them withmodels.getAvailableOfType("classifier")+models.classify()(enablecodemodewith"defaultTools": ["+codemode"]). Requires Pi >= 0.99.0; inert below (System One entries stay filtered out). Classifier models never appear in/model, and a disabled feature or an org policy that is off surfaces asClassifierResult.errorMessage(classification never throws).
Requirements
- Mainline pi (
@earendil-works/pi-coding-agent) >= 0.84.1 — the supported host. The version floor and the support guarantee below apply to mainline pi. - A LunaRoute account with access to at least one organization.
Host compatibility: the omp fork is
best-effort and not integration-tested on a real omp host: login and startup
no longer crash on it, but (a) the raw-API-key paste option is mainline-only —
omp logins use the browser flow; and (b) omp does not refresh the model
catalog live — an omp-only install has an empty model list until the store is
populated by running /login lunaroute once on mainline pi on the same
machine. Report omp-specific issues at
https://github.com/lunaroute/lunaroute-pi-extension/issues.
Quick start
pi install npm:@lunaroute/pi-extension
Then in Pi:
/login lunaroute
Choose Log in with browser (a browser opens to LunaRoute; after you
approve, an API key is issued and stored) or Paste an API key (paste an
existing lr_... key). After login, the first lunaroute/* model is selected
for you and remembered across restarts — run /model only if you want to pick a
different one.
LunaRoute MCP tools
When you are logged in, the extension registers first-class Pi tools backed by
the hosted LunaRoute MCP server (https://mcp.lunaroute.com/mcp) over a
direct Streamable HTTP connection — no MCP adapter extension involved:
web_search/web_fetch(when no other extension already provides them)generate_image/edit_image/upload_imageconvert_document
Your lr_ key is sent per request and never persisted to any MCP config.
- Logged out: no registration occurs (silent). Log in with
/login lunaroute. - After
/login lunaroutewith a rotated key: the tools' shared client is swapped to the fresh key, so rotation takes effect without restarting Pi. - Org/user/tool policy is enforced server-side and shapes
tools/list— an empty tool list is a valid outcome, not an error. - The MCP tools toggle in
/lunarouteis the master switch for every MCP-backed tool family; each family below has its own toggle too. - Coming from an older release? The extension no longer uses
pi-mcp-adapter. Remove it
with
pi remove npm:pi-mcp-adapterunless you use it for other MCP servers. (One-time session notice when it is still installed.) - Overriding
LUNAROUTE_MCP_URLsends yourlr_key to that endpoint; prefer HTTPS in production (HTTP is intended only for local development).
Web tools
When you are logged in and no other extension already provides web
search, the extension registers a first-class web_search Pi tool that
calls the hosted LunaRoute MCP server directly (Streamable HTTP) with your
lr_ key and the usual attribution headers — no pi-mcp-adapter install
required.
- Detect-and-backfill. At
session_startthe extension checks every registered tool (built-ins, other extensions, adapter-prefixed names such aslunaroute_web_search). If a web search tool already exists — e.g. from pi-web-access or pi-web-search — LunaRoute stays silent: pi resolves cross-extension tool-name conflicts first-registration-wins, so a duplicate registration would be a silent no-op anyway. - Server-gated. The tool set is registered only for capabilities the
hosted MCP server actually offers (
tools/listis consulted once). As of v0.5.0 the server exposesweb_search({ query, count?, provider? }→ normalized results);web_fetchwill register automatically once the server ships it. - Parallel by default. Pi executes sibling tool calls concurrently — the
tool description nudges the model to batch multiple
web_searchcalls in one message. Output is truncated per pi's tool rules (50 KB / 2000 lines) and oversized results are spilled to a temp file the model can read. - Rendering. Collapsed one-line summaries (
✓ 5 results · brave), expandable to the full result list (title / URL / snippet), spinner while searching. Headless modes skip rendering; the text content still reaches the model. - Kill switch. Set
LUNAROUTE_WEB_TOOLS=offto disable. Tool-name overrides:LUNAROUTE_MCP_WEB_SEARCH_TOOL,LUNAROUTE_MCP_WEB_FETCH_TOOL. - Logged out: no tools are registered (silent), mirroring MCP registration.
If both this extension and another web-search extension are active, pi's
first-wins rule decides who owns the plain web_search name; use
--exclude-tools if you need to pick manually.
Image tools
When you are logged in, the extension registers first-class
generate_image, edit_image, and upload_image Pi tools backed by the
hosted LunaRoute MCP server — the same direct Streamable HTTP transport as
the web tools, no pi-mcp-adapter install required.
- No local detection. Unlike
web_search, these names are LunaRoute-specific: the extension registers whatever the hosted server offers for your org (tools/listgates entitlement, policy, and the image kill switch server-side). - Files on disk. Generated and edited images are saved to a per-
installation folder —
<agentDir>/lunaroute-images/(default~/.pi/agent/lunaroute-images/) — namedimg_<id>.<format>. The tool result tells the model the absolute path, theimg_…id (for lateredit_imagecalls), and the time-limited URL. Relocate the folder withLUNAROUTE_IMAGE_DIR. - Model awareness. The per-org model enum and each model's limits
(default size, step range, formats) are baked into the tool schema from
tools/list, so the model picks valid parameters instead of guessing. - Uploads.
upload_imagetakes a localpath(the extension does the base64) or aurl; the server sniffs the codec. Files over the 11 MiB server ceiling are rejected before upload. The returnedimg_…id feedsedit_image'simage_ids. - Kill switch.
/lunaroute→ Image tools toggle, orLUNAROUTE_IMAGE_TOOLS=off. Logged out: nothing registers (silent).
Convert tools
When you are logged in, the extension registers a first-class
convert_document Pi tool backed by the hosted LunaRoute MCP server —
documents (Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, PDF) and
raster images (OCR'd) become Markdown the model can work with.
- Inputs. A local
path(the extension reads and base64s it) or an http(s)url;filenameis derived from the path and can be set explicitly (required for CSV);ocr: trueruns the configured OCR backend on scanned PDFs (the server answersneeds_ocrwhen a scan requires it — retry withocr: true). - Format guard. Binary formats are magic-sniffed locally (ZIP-family, PDF, RTF, images) and text must be valid UTF-8 — unrecognized input is rejected before any bytes leave the machine.
- Output. Markdown comes back inline (truncated per pi's tool rules,
spilled to a temp
.mdfor big documents). When the server reportsoutput_too_large, the tool automatically retries with the stored-artifact path and saves the full markdown to a per-installation folder —LUNAROUTE_DOCS_DIR(default<agentDir>/lunaroute-docs) — returning the path and a head. Note: with the server's stock size caps this fallback only succeeds on deployments that raiseMCP_DOC_MAX_OUTPUT_BYTESabove the embed cap; otherwise the error is surfaced cleanly. - Kill switch.
/lunaroute→ Convert tools toggle, orLUNAROUTE_CONVERT_TOOLS=off.
Settings
Run /lunaroute in Pi for a menu — Settings (or /lunaroute settings)
opens the settings UI below, Refresh models (or /lunaroute models-refresh)
reloads the model catalog from LunaRoute without a restart, and Usage (or
/lunaroute usage) prints this period's usage. A refresh that
fails (network down, rejected key, timeout) is reported as an error and the
last known catalog stays in use. The settings UI, interactive mode only:
- MCP tools — on/off. Off skips the hosted LunaRoute MCP registration (a server you configured yourself is always left alone).
- Web search tools — on/off. Off removes
web_search/web_fetchimmediately; on restores them without a restart. - Search provider — server / brave / exa / kagi / youcom. The default provider
used for every
web_search; the model can still override it per call. Hand-editinglunaroute.jsonalso acceptsyouandyou.com; both are stored asyoucom. - Image tools — on/off. Off removes
generate_image/edit_image/upload_imageimmediately; on restores them without a restart. - Convert tools — on/off. Off removes
convert_documentimmediately; on restores it without a restart (revalidating the server catalog). - Usage insights — on/off, on by default. When on, each LunaRoute
response's queue time is accumulated for the session,
/lunaroute usagereports it, and one advisory message is shown per Pi process when the server reports heavy queueing. Off suppresses the checks and the data; the command then only says insights are off. Independent of the MCP tools master switch.
/lunaroute usage shows the plan and lane count, the billing period, queued
and rejected totals, and this session's own measured queueing. The server
supplies the snapshot (plan limits, status, and upgrade wording); when it is
unavailable the command falls back to the session's measurements. Requires a
LunaRoute gateway that sends x-lunaroute-queue-ms and offers the get_usage
MCP tool — older servers simply report nothing.
Settings persist in ~/.pi/agent/lunaroute.json:
{ "mcp": "on", "webTools": "on", "searchProvider": "server", "imageTools": "on", "convertTools": "on", "usageInsights": "on" }
Missing keys fall back to these defaults (which equal the pre-settings
behavior), and invalid values are ignored per key. Outside interactive mode,
edit the file directly. The LUNAROUTE_WEB_TOOLS environment variable (see
below) still wins over the file.
Configuration
The gateway, API, and front URLs default to production and are overridable for dev/staging via environment variables before starting Pi:
| Variable | Default | Purpose |
|---|---|---|
LUNAROUTE_ROUTING_URL |
https://gw.lunaroute.com/v1 |
Gateway base URL (provider baseUrl + /models) |
LUNAROUTE_API |
responses |
Wire format: responses (OpenAI Responses API, gw/v1/responses) or completions (chat completions kill switch). An unrecognized value warns and falls back to completions. |
LUNAROUTE_API_URL |
https://api.lunaroute.com |
API host for /v1/auth/exchange |
LUNAROUTE_FRONT_URL |
https://app.lunaroute.com |
Web app host for /device-auth/pi browser login |
LUNAROUTE_MCP_URL |
https://mcp.lunaroute.com/mcp |
Hosted MCP server URL behind the first-class MCP-backed tools |
LUNAROUTE_IMAGE_DIR |
<agentDir>/lunaroute-images |
Where generated/edited images are saved (kata e30g) |
LUNAROUTE_IMAGE_TOOLS |
(unset) | Set to off/0/false to disable the first-class image tools |
LUNAROUTE_DOCS_DIR |
<agentDir>/lunaroute-docs |
Where oversized converted documents are saved (kata zpzt) |
LUNAROUTE_CONVERT_TOOLS |
(unset) | Set to off/0/false to disable the first-class convert_document tool |
LUNAROUTE_USAGE_INSIGHTS |
(unset) | Set to off/0/false to disable usage insights (queue collection, /lunaroute usage, advisory message) |
Troubleshooting
- No models appear after login: the gateway may be unreachable, or the key
may be stale. Re-run
/login lunaroute. A model the gateway lists without a context window is skipped rather than shown with a zero window. - Requests fail with 401: the stored key was rotated or revoked. Pi warns
once per session; run
/login lunarouteto store a new one. - First-run hint: if you have not logged in,
session_startshowsRun /login lunaroute to start using LunaRoute.
Development
npm install
npm run check
pi -e .
Manual smoke test:
- Run
pi -e ., then/login lunaroute, pick browser, complete the flow. - Confirm a model appears in
/model. - Send a request; confirm LunaRoute receives the attribution headers.
- Repeat with the paste path.
- On a fresh profile with no key, confirm the first-run hint appears and no error is thrown.
- Logged in, confirm the first-class LunaRoute tools appear (
/tools) andgenerate_imageworks end-to-end. - With pi-mcp-adapter still installed, confirm the one-time migration notice at session start; logged out, confirm silence.
- Web tools: logged in with no other web-search extension installed, ask
the agent to search the web — the
web_searchtool should appear in the tool list, run, and render collapsed with expandable sources. With pi-web-access installed, confirm LunaRoute registers nothing (pi.getAllTools()shows the other extension'sweb_search).
Package dry run:
npm pack --dry-run
License
MIT License. See LICENSE.