Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
25ddae0
fix(nvpair-engine-manager): stop slow-starting engines cleanly
nvtushark Oct 28, 2026
41be635
feat(nvpair-engine-manager): list Hugging Face cache models with hf_c…
nvtushark Oct 28, 2026
16718a8
feat(nvpair-engine-manager): switch an engine's model with launch_model
nvtushark Oct 28, 2026
8dd501d
feat(services): add vLLM as an inference engine
nvtushark Oct 28, 2026
1b9e57d
test(services): cover the bundled vLLM manifest and proxy interop
nvtushark Oct 28, 2026
bb2065d
feat(desktop): add vLLM engine support and docs
nvtushark Oct 16, 2026
07cdf21
fix(nvpair-engine-manager): cap vLLM default context length
nvtushark Oct 16, 2026
8f65d1e
fix(desktop): keep vLLM shown as starting while a model switch restar…
nvtushark Oct 16, 2026
57a2b05
feat(nvpair-engine-manager): size vLLM context, GPU share and tool ca…
nvtushark Oct 21, 2026
edc9b11
feat(nvpair-engine-manager): download and browse Hugging Face models …
nvtushark Oct 21, 2026
79325c9
feat(desktop): offer Add model and hub search for vLLM
nvtushark Oct 21, 2026
29b994a
feat: delete cached Hugging Face models for vLLM
nvtushark Oct 21, 2026
d860319
feat: eject vLLM models by stopping the engine, and free blobs on delete
nvtushark Oct 21, 2026
4e8d2f4
feat(nvpair-engine-manager): put a gateway in front of vLLM
nvtushark Oct 21, 2026
37fadc5
feat(nvpair-engine-manager): unload an idle vLLM and keep its engine on
nvtushark Oct 21, 2026
76c3123
feat(nvpair-engine-manager): load an unloaded vLLM on the first request
nvtushark Oct 21, 2026
35eef76
fix(nvpair-engine-manager): keep an unloaded vLLM routable through th…
nvtushark Oct 21, 2026
a335b38
fix(nvpair-engine-manager): no health warning while vLLM is unloaded …
nvtushark Oct 21, 2026
44a6c22
feat(nvpair-engine-manager): start vLLM lazily and make its idle time…
nvtushark Oct 21, 2026
6373a80
feat(desktop): show an idle vLLM and let its idle limit be chosen
nvtushark Oct 21, 2026
056456d
feat: default the vLLM idle limit to five minutes
nvtushark Oct 21, 2026
d562baf
feat(nvpair-engine-manager): install vLLM on Apple Silicon macOS
nvtushark Oct 23, 2026
0a94a2c
feat(nvpair-engine-manager): switch vLLM models on request
nvtushark Oct 28, 2026
7c0f178
fix(nvpair-engine-manager): harden vLLM model switching after review
nvtushark Oct 28, 2026
70abdbc
docs: bring the vLLM docs up to date with the branch
nvtushark Oct 28, 2026
86e94a4
feat(nvpair-engine-manager): find a model's vLLM tool-call parser
nvtushark Oct 29, 2026
8c6f773
feat(nvpair-engine-manager): choose vLLM's tool-call parser per model
nvtushark Oct 29, 2026
b444743
feat(nvpair-engine-manager): answer tool requests to a vLLM without a…
nvtushark Oct 29, 2026
ad32c11
fix(nvpair-engine-manager): leave out engines this host cannot run
nvtushark Oct 29, 2026
a0eff8f
fix(desktop): hide engines a node cannot run
nvtushark Oct 29, 2026
5c27d65
fix(nvpair-engine-manager): wait for remote vLLM loads and always res…
nvtushark Oct 30, 2026
74f8e14
fix(nvpair-engine-manager): address review comments on vLLM support
nvtushark Oct 30, 2026
2e300f2
Merge develop into vllm-engine-support
nvtushark Oct 30, 2026
1158c32
Merge develop into vllm-engine-support
nvtushark Nov 3, 2026
eae0fde
refactor(nvpair-engine-manager): remove the vLLM gateway
nvtushark Nov 3, 2026
4b115ca
feat(desktop): drop the vLLM idle state and idle-limit control
nvtushark Nov 3, 2026
ba929c6
docs(nvpair-ui-broker): list the vLLM facade in the broker spec
nvtushark Nov 3, 2026
83dde0b
fix(nvpair-engine-manager): size the first vLLM start for its model
nvtushark Nov 4, 2026
adae50a
fix(nvpair-engine-manager): download a Mistral model once, in the for…
nvtushark Nov 4, 2026
120ae08
fix(nvpair-engine-manager): pin mistral_common for vLLM 0.32
nvtushark Nov 4, 2026
dfbbcfb
fix(nvpair-engine-manager): delete vLLM models with hf cache rm
nvtushark Nov 4, 2026
daf08cb
fix(vllm): keep a vLLM's downloaded models listed on every node
nvtushark Nov 5, 2026
f2a0020
fix(nvpair-engine-manager): one lock for vLLM launch changes, and con…
nvtushark Nov 5, 2026
c7b5e7c
fix(nvpair-engine-manager): refuse FP8 models vLLM-Metal cannot load
nvtushark Nov 5, 2026
5c5eafe
refactor(nvpair-engine-manager): share the Hugging Face catalog fetch…
nvtushark Nov 5, 2026
d0058b0
fix(desktop): one pending action for a vLLM Load, and Start pending t…
nvtushark Nov 5, 2026
c6d978f
test: use testify and the helper-closure table style in the vLLM tests
nvtushark Nov 5, 2026
f48631c
fix(nvpair-engine-manager): let Stop and Eject cancel a start in flight
nvtushark Nov 5, 2026
988be73
fix(nvpair-engine-manager): choose vLLM's tool-call parser from the c…
nvtushark Nov 5, 2026
90f5cb3
fix(desktop): keep a starting engine stoppable
nvtushark Nov 5, 2026
632a2a0
style(nvpair-engine-manager): rewrap the restore comment
nvtushark Nov 5, 2026
5af6949
fix(nvpair-engine-manager): read vLLM's Hugging Face cache, endpoint …
nvtushark Nov 5, 2026
b0d6d9d
test(nvpair-engine-manager): always release the fake hf tool in the d…
nvtushark Nov 5, 2026
28ec957
fix(nvpair-engine-manager): push engine:models-changed when a model i…
nvtushark Nov 5, 2026
98431a6
fix(nvpair-engine-manager): report a start refused before launch as a…
nvtushark Nov 5, 2026
8b3fa34
fix(vllm): reply that a Load the user stopped was stopped, not failed
nvtushark Nov 5, 2026
a579c6f
style(nvpair-engine-manager): rewrap the model watcher comment
nvtushark Nov 5, 2026
eb0637f
fix(nvpair-engine-manager): report an engine as starting while its st…
nvtushark Nov 5, 2026
24601ba
fix(nvpair-tui): show a starting engine, and download into a stopped …
nvtushark Nov 5, 2026
3ad2f60
fix(nvpair-engine-manager): refuse a vLLM download that cannot make a…
nvtushark Nov 5, 2026
2a05446
fix(desktop): show who published each model in Add model
nvtushark Nov 5, 2026
f30c5af
fix(nvpair-engine-manager): read Hugging Face settings and download p…
nvtushark Nov 5, 2026
1aad312
fix(nvpair-engine-manager): keep a vLLM start inside the remote budge…
nvtushark Nov 5, 2026
b342762
fix(nvpair-engine-manager): choose vLLM's weights with one rule, by t…
nvtushark Nov 5, 2026
678bacb
refactor: use the standard slices and maps helpers, and build engine …
nvtushark Nov 5, 2026
ced0a21
fix(nvpair-ui-broker): deliver a Stop while a Start is still loading,…
nvtushark Nov 5, 2026
16f8b93
refactor(nvpair-engine-manager): fetch a starting model's metadata on…
nvtushark Nov 5, 2026
518a339
fix(nvpair-engine-manager): use vLLM's --download-dir for the model l…
nvtushark Nov 5, 2026
4e5e6db
test: use t.Context() in the tests this change adds
nvtushark Nov 5, 2026
67ed674
refactor(desktop): derive proxy identities from the shared engine-nam…
nvtushark Nov 5, 2026
b390528
fix(nvpair-engine-manager): answer a Restart that a Stop cut short wi…
nvtushark Nov 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ one, and both report live GPU and memory use throughout.
| **Architectures** | x64 and arm64 on all three. Windows on ARM is experimental. |
| **Installers** | Windows `.exe`; Linux `.deb`; macOS `.dmg`. On other Linux distributions, [build from source](docs/building.mdx). |
| **Mixing nodes** | Windows, Linux, and macOS nodes can all be paired with each other |
| **Inference engines** | Ollama, LM Studio, and llama.cpp |
| **Inference engines** | Ollama, LM Studio, llama.cpp, and vLLM (Linux with an NVIDIA GPU, or Apple Silicon macOS) |

**PAIR running on a machine does not mean an engine will.** PAIR itself runs on
any supported Windows, Linux, or macOS machine. Each engine sets its own requirements
Expand Down Expand Up @@ -100,7 +100,7 @@ you want by its full filename instead.
**Settings → Service** and read the status there.

- **Get an engine running.** On the node's card, open **Engine settings** and
select **Install** next to Ollama, LM Studio, or llama.cpp. PAIR downloads and
select **Install** next to Ollama, LM Studio, llama.cpp, or (on Linux or Apple Silicon macOS) vLLM. PAIR downloads and
sets the engine up for you, so nothing needs to be in place beforehand.

![The Install engines dialog with Ollama downloading, reporting progress as it installs.](docs/assets/onboarding/engine-lifecycle/01-engine-installing.png)
Expand Down Expand Up @@ -199,7 +199,7 @@ Your data means settings, logs, cluster identity and certificates, and any engin
PAIR installed for you. An engine the uninstaller cannot remove — one still
holding a file open, say — is left in place rather than stopping the uninstall;
remove it with its own uninstaller. **Model weights are not touched** — they live in the
engine's own storage (`~/.ollama`, `~/.llamacpp`, `~/.lmstudio/models`), so
engine's own storage (`~/.ollama`, `~/.llamacpp`, `~/.lmstudio/models`, `~/.cache/huggingface`), so
removing PAIR does not delete the models you downloaded. Delete those through the
engine, or by removing its directory. An engine you installed yourself is also
left alone.
Expand Down Expand Up @@ -284,7 +284,7 @@ feedback and contributions will help shape priorities.
### Engines and integrations

- [x] llama.cpp support.
- [ ] vLLM support.
- [x] vLLM support.
- [ ] EXO support.
- [ ] ComfyUI integration.
- [ ] Unsloth support.
Expand Down
4 changes: 2 additions & 2 deletions desktop/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ not select or pin proxy routes.
An NVPAIR-launched engine binds to loopback and is never directly LAN-reachable.
Peers reach it only through the node's proxy over a cluster-mTLS ingress, so
discovery advertises the promoted proxy port for `ol`/`lm` rather than the
engine's private port; llama.cpp uses the additional `lc` key. Transport
engine's private port; llama.cpp uses the additional `lc` key and vLLM the `vl` key. Transport
security is backend-owned; Electron only
reflects the advertised proxy port and reads a remote engine's real port from
`engine:remote-get-installed` facts.
Expand Down Expand Up @@ -408,7 +408,7 @@ deletes finish. Unpackaged (`electron-vite dev`) builds omit relaunch and the UI
tells the developer to run `npm start` again — quitting Electron tears down the Vite
renderer server, so auto-relaunch would come up with nothing to load.

The engines' model stores (`~/.ollama`, `~/.llamacpp`, `~/.lmstudio/models`) and
The engines' model stores (`~/.ollama`, `~/.llamacpp`, `~/.lmstudio/models`, `~/.cache/huggingface`) and
the application install tree are never removed. The reset does uninstall the
engines PAIR installed, through `engine:uninstall-managed` while the broker is
still running, so an engine a vendor installer placed in the user's home is
Expand Down
16 changes: 12 additions & 4 deletions desktop/docs/frontend-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,19 @@ They do not imply a WebSocket connection. Browser clients are not supported.
- `onSettingsDisconnected(callback)` reports that a node's settings authority
became unreachable, so its cached snapshot is stale.

`EngineType` currently includes `ollama`, `lm-studio`, and `llama-cpp`.
`EngineType` currently includes `ollama`, `lm-studio`, `llama-cpp`, and `vllm`.
vLLM serves one model per process, so `unloadModel` (Eject) stops the engine,
which frees its GPU memory, and `loadModel` on a stopped engine starts it. Its model
list is the Hugging Face cache, which stays available while the engine is stopped, `deleteModel` removes a cached model (not the one
loaded in vLLM; deleting an ejected or stopped vLLM's model leaves it with no model
selected until `loadModel` picks one), `pullModel` downloads a Hugging Face repo into
that cache (no running engine needed), and `loadModel` on a cached model switches
the served model by restarting vLLM on it.
`searchHub(engineType, query?)` serves Ollama's locked local catalog and cached
live Hugging Face catalogs for LM Studio and llama.cpp. A non-empty llama.cpp
query performs an explicit bounded search across public Hugging Face GGUF
repositories; other calls return the populated engine catalog. llama.cpp pull
live Hugging Face catalogs for LM Studio, llama.cpp and vLLM. A non-empty
llama.cpp or vLLM query performs an explicit bounded search across public
Hugging Face repositories (GGUF for llama.cpp, safetensors chat models for vLLM);
other calls return the populated engine catalog. llama.cpp pull
IDs are exact `owner/repository:quantization` values; load, unload, and delete
all use that same exact id.

Expand Down
3 changes: 3 additions & 0 deletions desktop/docs/services-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
- ⚠️ nvpair-proxy → node/set-local-backend
- ⚠️ nvpair-ui-broker → discovery:unsubscribe
- ⚠️ nvpair-ui-broker → engine:configure-launch
- ⚠️ nvpair-ui-broker → engine:restart
- ⚠️ nvpair-ui-broker → engine:set-port
- ⚠️ nvpair-ui-broker → engine:set-reserved-port
- ⚠️ nvpair-ui-broker → engine:unsubscribe
Expand Down Expand Up @@ -270,9 +271,11 @@
| `engine:get-settings` | request (we call) | ✅ yes |
| `engine:install` | request (we call) | ✅ yes |
| `engine:preview-settings` | request (we call) | ✅ yes |
| `engine:restart` | request (we call) | ⚠️ not called |
| `engine:set-port` | request (we call) | ⚠️ not called |
| `engine:set-reserved-port` | request (we call) | ⚠️ not called |
| `engine:start` | request (we call) | ✅ yes |
| `engine:stop` | request (we call) | ✅ yes |
| `engine:subscribe` | request (we call) | ✅ yes |
| `engine:unsubscribe` | request (we call) | ⚠️ not called |
| `errors:get-initial` | request (we call) | ✅ yes |
Expand Down
2 changes: 1 addition & 1 deletion desktop/docs/services-backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ reserved for inference clients.
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `app:ready` | Complete broker startup and refresh snapshots | `state:request-refresh` |
| `discovery:nodes-changed` | Replace discovery snapshot and diff nodes | `discovery:nodes-changed`, `nodes:upsert`, `nodes:remove` |
| `ollama-proxy:ready` / `lmstudio-proxy:ready` / `llamacpp-proxy:ready` | Record engine proxy port | `engines:state-changed` |
| `ollama-proxy:ready` / `lmstudio-proxy:ready` / `llamacpp-proxy:ready` / `vllm-proxy:ready` | Record engine proxy port | `engines:state-changed` |
| proxy `node/*` | Update per-engine node presence; the advertised port is the peer's promoted proxy port (not the engine's private loopback port) | node and engine pushes |
| `engine:ready` / `engine:state-changed` | Update engine facts and models | `engines:state-changed` |
| `engine:settings-changed` | Validate and republish the owning node's settings snapshot | `engines:settings-changed` |
Expand Down
Loading
Loading