@computesdk/pi-morph1.0.7
Morph for Pi: open-weight coding models (Kimi K3, GLM 5.3, DeepSeek V4) on Morph's OpenAI-compatible API, plus Fast Apply, Compact, and WarpGrep as 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
@computesdk/pi-morph
Morph for Pi: the open-weight coding models as a provider, and Morph's single-purpose models as tools.
pi install npm:@computesdk/pi-morph # or: pi -e /path/to/pi-extensions/packages/pi-morph
Run /login morph and paste your key, or set MORPH_API_KEY in your environment; one credential covers both halves (the models and the tools). When both are set the stored key wins, which is what the models do too, so /login is the one that decides — unset it, or point PI_CODING_AGENT_DIR at another directory, to switch back to the environment variable.
Models
Set the key and the models show up in /model as morph/morph-kimik3 and friends.
| Model | Input | Context | $/1M in | $/1M out |
|---|---|---|---|---|
morph-kimik3 — Kimi K3 |
text | 1M | 2.50 | 14.00 |
morph-kimik3-fast — Kimi K3 Fast |
text | 1M | 6.00 | 22.50 |
morph-glm53-744b — GLM-5.3 744B |
text | 1M | 1.19 | 6.00 |
morph-glm53flash — GLM-5.3 Flash |
text, image | 1M | 0.20 | 0.70 |
morph-dsv41flash — DeepSeek V4.1 Flash |
text, image | 1M | 0.12 | 0.80 |
morph-dsv41flash-1017 — DeepSeek V4.1 Flash 1017 |
text, image | 1M | 0.12 | 0.80 |
morph-dsv4flash — DeepSeek V4 Flash 0731 |
text | 1M | 0.14 | 0.40 |
Endpoint https://api.morphllm.com/v1, bearer auth, api: "openai-completions" — Pi's built-in implementation does the request, stream and tool-call plumbing, so the provider is one pi.registerProvider call with the catalog above. Prices are per 1M tokens from morphllm.com/pricing; cacheWrite is not billed. service_tier: "standby" halves the price on supported models — Pi can send it through samplingParams.
Pi's thinking levels map onto Morph's reasoning_effort ladder (none | low | high | xhigh | max). DeepSeek documents none, so off maps to it; for the other models off is marked unsupported (null) rather than sent.
The -1017 in DeepSeek's ID is a snapshot date — October 17 — matching 0731 for July 31 in morph-dsv4flash. So morph-dsv41flash-1017 is pinned to those weights while morph-dsv41flash follows whatever Morph serves today; the two share a serving pool and list prices.
Tools
The same package adds three tools. Morph's single-purpose models take request shapes of their own rather than chat completions, so they are tools here, not entries in the catalog above.
| Tool | What it does | Endpoint |
|---|---|---|
morph_apply |
Applies an edit to a file with Fast Apply (~10.5k tok/s, ~98% accuracy) | POST /v1/code/apply |
morph_compact |
Compresses long text, keeping the parts a follow-up question needs | POST /v1/compact |
morph_search |
Answers a code question with the WarpGrep search subagent (~6s) | POST /v1/chat/completions with morph-warp-grep-v2.1 |
morph_apply rewrites the file it is given: you pass the lines that change plus // ... existing code ... markers for the unchanged spans, and Morph merges the edit in. It is marked destructiveHint, so a permission extension can gate it. The other two only read.
morph_apply offers the models /v1/code/apply actually serves — morph-v3-fast (the default), morph-v2, morph-v0. Morph's docs also list auto and morph-v3-large, but the deployed endpoint rejects both with 400 invalid_request_error, so they are not offered here.
morph_compact filters line by line, so an input with nothing worth keeping for the question comes back as (filtered N lines) rather than as text — a one-line input always does. The tool explains that instead of echoing the marker bare.
morph_search is a subagent, not a grep wrapper. It explores the repository in its own context window for up to six turns and returns only the file/line spans it settled on, with their code, so the dead ends never reach your context. Its search tools (grep_search, read, list_directory, glob, finish) are built into Morph's model; this package executes them locally and feeds the results back.
That local implementation never runs a shell. Morph asks for directory listings as shell commands (ls -la src), which are parsed here rather than executed, and every read is confined to the directory the search was given. node_modules, .git, and build or virtualenv trees are skipped.
Usage from these endpoints is reported to Pi without a cost, because Morph does not publish per-token prices for them.
Not included
The Model Router (/v1/router/classify, /v1/router/multimodel) labels how complex a prompt is so a caller can choose a model. It is left out because Pi already picks the model for a session, so there is nothing for a tool to decide.
Development
pnpm test # tsc --noEmit && node test.ts — offline unit tests
bash scripts/smoke.sh morph # real requests, from the repo root; needs a key
test.ts loads both extensions with a fake Pi. It checks the provider config and every registered model — id, name, modalities, context and output limits, costs, uniqueness, and that each Pi thinking level is either mapped to a provider value or explicitly unsupported — then exercises the tools' local search implementation against a scratch directory: the repo structure WarpGrep is handed, argument coercion for grep/read/list_directory/glob, the text form of WarpGrep's tool calls, span parsing, path confinement, and usage mapping. Nothing in the suite touches the network.
Because it cannot notice a vendor changing under us, scripts/smoke.sh (or pnpm smoke) covers that: it checks every declared model ID against the IDs Morph serves, sends one chat request per model, and calls each tool endpoint — including every model in APPLY_MODELS, which is what broke when Morph stopped serving auto.
MIT licensed.