pi-free 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -12
- package/README.md +44 -97
- package/config.ts +24 -52
- package/constants.ts +6 -0
- package/index.ts +175 -148
- package/lib/built-in-toggle.ts +40 -1
- package/lib/model-enhancer.ts +20 -20
- package/lib/open-browser.ts +1 -1
- package/lib/provider-compat.ts +46 -0
- package/lib/registry.ts +193 -144
- package/lib/types.ts +101 -108
- package/lib/util.ts +256 -256
- package/package.json +8 -8
- package/provider-failover/benchmark-lookup.ts +2 -2
- package/provider-helper.ts +19 -1
- package/providers/cline/cline-auth.ts +473 -473
- package/providers/cline/cline.ts +31 -4
- package/providers/crofai/crofai.ts +170 -0
- package/providers/dynamic-built-in/index.ts +258 -308
- package/providers/kilo/kilo-auth.ts +155 -155
- package/providers/kilo/kilo.ts +263 -235
- package/providers/nvidia/nvidia.ts +476 -415
- package/providers/ollama/ollama.ts +295 -280
- package/providers/opencode-session.ts +3 -4
- package/providers/qwen/qwen-models.ts +101 -101
- package/providers/zenmux/zenmux.ts +176 -0
- package/scripts/check-extensions.mjs +64 -55
- package/provider-factory.ts +0 -207
- package/providers/cloudflare/cloudflare.ts +0 -526
- package/providers/modal/modal.ts +0 -47
package/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,88 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [2.0.4] - 2026-05-02
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **OpenRouter key resolution no longer falls back to `free.json`** —
|
|
13
|
+
`getOpenrouterApiKey()` now only checks the `OPENROUTER_API_KEY` environment variable.
|
|
14
|
+
Previously it fell back to `~/.pi/free.json`, which could contain stale/revoked keys
|
|
15
|
+
that conflict with pi's built-in OpenRouter provider (which reads from
|
|
16
|
+
`~/.pi/agent/auth.json`).
|
|
17
|
+
|
|
18
|
+
- **Removed `openrouter_api_key` from `PiFreeConfig` interface and config template** —
|
|
19
|
+
Prevents future persistence of OpenRouter keys in `free.json`, eliminating the
|
|
20
|
+
source of stale key conflicts for built-in providers.
|
|
21
|
+
|
|
22
|
+
## [2.0.3] - 2026-05-02
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Consistent `isFreeModel` helper with Route A/B logic** — Created a unified helper for free model detection that automatically detects whether a provider exposes pricing:
|
|
27
|
+
|
|
28
|
+
- **Route A (pricing-exposed)**: Model is free if `cost === 0` OR `"free"` in name (OR logic)
|
|
29
|
+
- **Route B (non-pricing-exposed)**: Model is free only if `"free"` in name
|
|
30
|
+
- Dynamic detection: If ALL models have cost === 0, assumes pricing not exposed → uses Route B
|
|
31
|
+
- If ANY model has cost > 0, assumes pricing exposed → uses Route A
|
|
32
|
+
- All providers (Cline, Kilo, NVIDIA, Ollama, dynamic built-in) now use this consistent helper
|
|
33
|
+
|
|
34
|
+
- **CrofAI provider (PAID)** — Added new **paid** provider for CrofAI (https://crof.ai), an OpenAI-compatible LLM inference API. **Note: CrofAI is a paid provider** — users must have a CrofAI API key with credits. The provider uses Route B detection (name-only) since CrofAI's API doesn't expose per-model pricing. Only models with `"free"` in their names are marked as free (none currently).
|
|
35
|
+
|
|
36
|
+
- **ZenMux provider (PAID)** — Added new **paid** provider for ZenMux AI gateway (https://zenmux.ai), a unified API for 200+ models from OpenAI, Anthropic, Google, etc. **Note: ZenMux is a paid provider** — users must have a ZenMux API key with credits. The provider uses Route A detection (OR logic) since ZenMux exposes pricing. Models marked as free only if `cost === 0` OR `"free"` in name (2 free models identified: GLM 4.7 Flash Free, GLM 4.6v Flash Free).
|
|
37
|
+
|
|
38
|
+
- **Comprehensive `isFreeModel` test suite** — Added 30+ unit tests covering Route A, Route B, freemium behavior, and edge cases. Tests verify correct classification on actual OpenRouter API data (371 models, 30 free).
|
|
39
|
+
|
|
40
|
+
- **Toggle commands for dynamic built-in providers** — Added `/toggle-mistral`, `/toggle-groq`,
|
|
41
|
+
`/toggle-cerebras`, `/toggle-xai`, and `/toggle-huggingface` commands. These providers were
|
|
42
|
+
registered with the global toggle system but lacked per-provider toggle commands, making
|
|
43
|
+
free/paid switching inaccessible without editing config files.
|
|
44
|
+
|
|
45
|
+
- **Lazy auto-probe for NVIDIA models** — Extracted `runNvidiaProbe()` into a shared function
|
|
46
|
+
called automatically on first `session_start` (once per session). Previously, users had to
|
|
47
|
+
manually run `/probe-nvidia` to discover 404 models. Now broken models are detected and
|
|
48
|
+
auto-hidden on first use.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- **Cline provider now uses `isFreeModel`** — Fixed Cline to use the consistent `isFreeModel` helper instead of `m.cost.input === 0`. Previously used cost-only filtering, now uses proper OR logic for pricing-exposed providers.
|
|
53
|
+
|
|
54
|
+
- **NVIDIA test expectations updated** — Updated tests to reflect strict Route B behavior (name-only detection for non-pricing-exposed providers). Added test for models with `"free"` in name being marked as free.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- **`provider-factory.ts` — `beforeProviderRequest` hook now scoped to owning provider** —
|
|
59
|
+
The hook was firing for **all** provider requests regardless of which provider the factory
|
|
60
|
+
was configuring. Now checks `evt.provider !== def.providerId` and returns early if the
|
|
61
|
+
event doesn't belong to the owning provider.
|
|
62
|
+
|
|
63
|
+
- **`provider-factory.ts` — `reRegister` callback no longer corrupts stored model lists** —
|
|
64
|
+
When toggling between free/paid modes, the callback was overwriting `stored.all` with only
|
|
65
|
+
the filtered subset, losing the original full model list. Now preserves the original model
|
|
66
|
+
lists for correct subsequent toggling.
|
|
67
|
+
|
|
68
|
+
- **`lib/types.ts` — Removed leftover `LspTestInterface`** — Removed a test interface that
|
|
69
|
+
was left in production code.
|
|
70
|
+
|
|
71
|
+
- **`index.ts` — Removed redundant `.catch()` on deprecated Qwen provider** — The `.catch()`
|
|
72
|
+
was unnecessary since `Promise.allSettled` already handles rejections.
|
|
73
|
+
|
|
74
|
+
### Removed
|
|
75
|
+
|
|
76
|
+
- **Qwen provider (deprecated)** — Removed Qwen OAuth provider as the 1,000 req/day free tier is no longer available. Provider remains functional for existing authenticated users but new free tier registrations are not supported.
|
|
77
|
+
|
|
78
|
+
- **Modal provider** — Removed single-model Modal provider (only had GLM-5.1 FP8). Users should use other providers for GLM models.
|
|
79
|
+
|
|
80
|
+
- **Cloudflare provider** — Removed Cloudflare Workers AI provider as it's now built into pi core. Users can use pi's built-in Cloudflare provider instead.
|
|
81
|
+
|
|
82
|
+
- **Qwen test file** — Removed `tests/qwen.test.ts` along with the deprecated provider.
|
|
9
83
|
|
|
10
84
|
## [2.0.2] - 2026-04-26
|
|
11
85
|
|
|
12
86
|
### Added
|
|
13
87
|
|
|
14
88
|
- **Model matching debug logging** — Added `~/.pi/modelmatch.log` to diagnose which models get Coding Index scores and which don't:
|
|
89
|
+
|
|
15
90
|
- Logs every matching attempt with provider, model ID, normalization strategy, and result
|
|
16
91
|
- CSV-like format: `timestamp|provider|modelId|modelName|action|strategy|normalizedId|matchKey|codingIndex|details`
|
|
17
92
|
- Provider-specific normalizers for better matching:
|
|
@@ -26,6 +101,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
26
101
|
- **Enhanced benchmark lookup** — `enhanceModelNameWithCodingIndex()` now accepts optional `provider` parameter for provider-aware normalization
|
|
27
102
|
|
|
28
103
|
- **Static 404 model blocklist for NVIDIA** — Probed all 136 models from `integrate.api.nvidia.com/v1/models` and identified 57 that return 404 "Function not found" on `/v1/chat/completions`. These are now hard-filtered so they never appear in the model selector:
|
|
104
|
+
|
|
29
105
|
- Covers discontinued models (`databricks/dbrx-instruct`, `meta/codellama-70b`, `meta/llama2-70b`, `ibm/granite-*`, etc.)
|
|
30
106
|
- Covers embedding-only models listed as chat-capable (`nvidia/nv-embed-v1`, `nvidia/nv-embedqa-*`, `snowflake/arctic-embed-l`, etc.)
|
|
31
107
|
- Covers stale API catalog entries (`mistralai/mistral-large`, `mistralai/mistral-large-2-instruct`, `writer/palmyra-*`, etc.)
|
|
@@ -36,6 +112,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
36
112
|
- **`scripts/probe-nvidia.mjs`** — Standalone Node.js script to reproduce the probe. Reads `~/.pi/free.json` for the API key, batches 20 requests at a time with 10s timeout, and prints all broken model IDs for adding to the blocklist.
|
|
37
113
|
|
|
38
114
|
- **Ollama Cloud 403 handling** — Same pattern as NVIDIA 404s for Ollama Cloud:
|
|
115
|
+
|
|
39
116
|
- `OLLAMA_KNOWN_403_MODELS` blocklist for models that return 403 "access denied"
|
|
40
117
|
- `/probe-ollama` command to test all models on-demand, auto-hide broken ones, and re-register
|
|
41
118
|
- `scripts/probe-ollama.mjs` standalone script for blocklist maintenance
|
|
@@ -59,6 +136,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
59
136
|
### Changed
|
|
60
137
|
|
|
61
138
|
- **Cloudflare provider now fetches models dynamically** — Replaced static 19-model hardcoded list with live API fetch from `api.cloudflare.com/client/v4/accounts/{account_id}/ai/models`:
|
|
139
|
+
|
|
62
140
|
- Automatically discovers all 30+ text generation models (was manually maintaining 19)
|
|
63
141
|
- Smart filtering excludes embeddings, image generation, speech, translation, and vision-only models via regex patterns
|
|
64
142
|
- Metadata inference from model IDs: detects vision (`vision`/`multimodal`), reasoning (`r1`/`thinking`/`qwq`), context windows, and estimated costs
|
|
@@ -73,17 +151,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
73
151
|
- Graceful fallback to `models.dev` if NVIDIA API is unreachable
|
|
74
152
|
- Removed paid/free toggle filtering — NVIDIA is freemium (all models use free credits)
|
|
75
153
|
|
|
76
|
-
## [2.0.2] - 2026-04-24
|
|
77
|
-
|
|
78
|
-
### Fixed
|
|
79
|
-
|
|
80
|
-
- **Provider toggle state now persists reliably** — Follow-up fixes to the new `toggle-{provider}` flow ensure saved free-vs-all preferences are restored consistently across sessions for built-in and extension-managed providers.
|
|
81
|
-
- **Config parse errors are now logged** — Invalid `~/.pi/free.json` content is no longer ignored silently; startup parse failures are written to `~/.pi/free.log` to make misconfiguration easier to diagnose.
|
|
82
|
-
|
|
83
|
-
### Changed
|
|
84
|
-
|
|
85
|
-
- **README refreshed** — Clarified that provider toggle changes apply immediately, persist across restarts, and that malformed config is surfaced in the extension log.
|
|
86
|
-
|
|
87
154
|
## [2.0.1] - 2026-04-24
|
|
88
155
|
|
|
89
156
|
### Added
|
|
@@ -97,6 +164,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
97
164
|
### Changed
|
|
98
165
|
|
|
99
166
|
- **OpenRouter moved to built-in toggle system** — OpenRouter is now handled by `lib/built-in-toggle.ts` alongside OpenCode for a unified approach:
|
|
167
|
+
|
|
100
168
|
- Removed from `providers/dynamic-built-in/index.ts`
|
|
101
169
|
- Eliminated duplicate toggle command registration logic
|
|
102
170
|
- Consolidated toggle persistence with other built-in providers
|
|
@@ -128,6 +196,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
128
196
|
### Breaking Changes
|
|
129
197
|
|
|
130
198
|
- **Removed Fireworks provider** — Fireworks is now a built-in Pi provider (added in pi 0.68.1), so the extension's Fireworks provider has been removed to avoid conflicts:
|
|
199
|
+
|
|
131
200
|
- Deleted `providers/fireworks/fireworks.ts` and `tests/fireworks.test.ts`
|
|
132
201
|
- Removed all Fireworks configuration options from `config.ts` (`fireworks_api_key`, `fireworks_show_paid`)
|
|
133
202
|
- Users should now use Pi's built-in Fireworks support with `FIREWORKS_API_KEY`
|
|
@@ -150,6 +219,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
150
219
|
### Removed
|
|
151
220
|
|
|
152
221
|
- **Removed paid model warning on selection** — Deleted the `model_select` event handler that showed:
|
|
222
|
+
|
|
153
223
|
- `⚠️ Paid model selected (${model.id}). Use "/free off" to enable paid models.`
|
|
154
224
|
- This warning was redundant since the global `/free` toggle and provider toggles already control model visibility
|
|
155
225
|
|
|
@@ -167,6 +237,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
167
237
|
### Added
|
|
168
238
|
|
|
169
239
|
- **Cloudflare Workers AI provider** — New provider for Cloudflare's serverless GPU platform:
|
|
240
|
+
|
|
170
241
|
- 50+ open-source models: Llama 4, Mistral Small 3.1, Qwen 2.5/3, DeepSeek R1, Gemma 4, Kimi K2.5/2.6, and more
|
|
171
242
|
- **10,000 Neurons/day FREE tier** (resets daily at 00:00 UTC)
|
|
172
243
|
- **$0.011 per 1,000 Neurons** beyond free allocation
|
|
@@ -175,6 +246,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
175
246
|
- Create token at https://dash.cloudflare.com/profile/api-tokens
|
|
176
247
|
|
|
177
248
|
- **Unified dynamic built-in providers module** — New `providers/dynamic-built-in/` module that dynamically fetches models from Pi's built-in providers when users have API keys:
|
|
249
|
+
|
|
178
250
|
- **Mistral** (`MISTRAL_API_KEY`) — Fetches from `api.mistral.ai/v1/models`
|
|
179
251
|
- **Groq** (`GROQ_API_KEY`) — Fetches from `api.groq.com/openai/v1/models`
|
|
180
252
|
- **Cerebras** (`CEREBRAS_API_KEY`) — Fetches from `api.cerebras.ai/v1/models`
|
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
# pi-free-providers
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="banner.svg" alt="pi-free" width="100%" max-width="900">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
Free and paid AI model providers for [Pi](https://pi.dev). Access **free and paid models** from multiple providers in one install.
|
|
4
8
|
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
## What does pi-free do
|
|
8
12
|
|
|
9
|
-
**pi-free is a Pi extension that unlocks free AI models from multiple providers.**
|
|
13
|
+
**pi-free is a Pi extension that unlocks free and paid AI models from multiple providers.**
|
|
10
14
|
|
|
11
15
|
When you install pi-free, it:
|
|
12
16
|
|
|
13
|
-
1. **Registers free-tier providers** with Pi's model picker — Kilo, Cline, NVIDIA,
|
|
17
|
+
1. **Registers free-tier providers** with Pi's model picker — Kilo (free), Cline (free), NVIDIA (freemium), ZenMux (paid), CrofAI (paid), Ollama Cloud (freemium), and more
|
|
14
18
|
|
|
15
|
-
2. **Fetches models dynamically** from provider APIs —
|
|
19
|
+
2. **Fetches models dynamically** from provider APIs — NVIDIA NIM, ZenMux, CrofAI, and Pi's built-in providers (Mistral, Groq, Cerebras, xAI, Hugging Face, OpenRouter) when API keys are configured
|
|
16
20
|
|
|
17
21
|
3. **Filters to show only free models by default** for providers that expose pricing — You see only the models that cost $0 to use. Paid models are hidden until you explicitly toggle them on.
|
|
18
22
|
|
|
@@ -40,7 +44,7 @@ Start Pi and press `Ctrl+L` to open the model picker.
|
|
|
40
44
|
|
|
41
45
|
Free models are shown by default — look for the provider prefixes:
|
|
42
46
|
|
|
43
|
-
**✅
|
|
47
|
+
**✅ Free Models (no payment required):**
|
|
44
48
|
|
|
45
49
|
- `opencode/` — OpenCode models (no setup required; toggle with `/toggle-opencode`)
|
|
46
50
|
- `kilo/` — Kilo models (free models available immediately, more after `/login kilo`)
|
|
@@ -50,9 +54,13 @@ Free models are shown by default — look for the provider prefixes:
|
|
|
50
54
|
**🔄 Freemium (free tier with limits, then paid):**
|
|
51
55
|
|
|
52
56
|
- `nvidia/` — NVIDIA NIM models (1,000 free requests/month, then credits)
|
|
53
|
-
- `cloudflare/` — Cloudflare Workers AI (10K Neurons/day free tier, then $0.011/1K Neurons)
|
|
54
|
-
- `modal/` — GLM-5.1 FP8 via Modal (free promotional period until April 30, 2026)
|
|
55
57
|
- `ollama-cloud/` — Ollama Cloud models (usage-based free tier, resets every 5 hours + 7 days)
|
|
58
|
+
**💳 Paid Providers (API key with credits required):**
|
|
59
|
+
|
|
60
|
+
- `zenmux/` — ZenMux AI gateway (200+ models from OpenAI, Anthropic, Google, etc.)
|
|
61
|
+
- `crofai/` — CrofAI OpenAI-compatible API (streaming, reasoning models)
|
|
62
|
+
|
|
63
|
+
> **Note:** Paid providers may occasionally offer free models or promotional credits. The `isFreeModel` helper automatically detects free models based on provider pricing data or model names containing "free". For providers that don't expose pricing (like CrofAI), only models with "free" in their names are marked as free.
|
|
56
64
|
|
|
57
65
|
**🔧 Dynamic API Providers (fetched when API key configured):**
|
|
58
66
|
|
|
@@ -74,11 +82,14 @@ Want to see paid models too? Run the toggle command for your provider:
|
|
|
74
82
|
/toggle-openrouter # Toggle OpenRouter (✅ offers free models)
|
|
75
83
|
/toggle-cline # Toggle Cline (✅ offers free models)
|
|
76
84
|
/toggle-nvidia # Toggle NVIDIA (🔄 freemium)
|
|
77
|
-
/toggle-cloudflare # Toggle Cloudflare (🔄 freemium)
|
|
78
85
|
/toggle-ollama # Toggle Ollama Cloud (🔄 freemium)
|
|
79
86
|
/toggle-mistral # Toggle Mistral (🔧 dynamic - needs API key)
|
|
80
87
|
/toggle-groq # Toggle Groq (🔧 dynamic - needs API key)
|
|
81
88
|
/toggle-cerebras # Toggle Cerebras (🔧 dynamic - needs API key)
|
|
89
|
+
/toggle-xai # Toggle xAI (🔧 dynamic - needs API key)
|
|
90
|
+
/toggle-huggingface # Toggle Hugging Face (🔧 dynamic - needs HF_TOKEN)
|
|
91
|
+
/toggle-zenmux # Toggle ZenMux (💳 paid - needs API key with credits)
|
|
92
|
+
/toggle-crofai # Toggle CrofAI (💳 paid - needs API key with credits)
|
|
82
93
|
```
|
|
83
94
|
|
|
84
95
|
**Notes:**
|
|
@@ -106,8 +117,6 @@ Add your API keys to this file:
|
|
|
106
117
|
{
|
|
107
118
|
"openrouter_api_key": "sk-or-v1-...",
|
|
108
119
|
"nvidia_api_key": "nvapi-...",
|
|
109
|
-
"cloudflare_api_token": "...",
|
|
110
|
-
"cloudflare_account_id": "...",
|
|
111
120
|
"ollama_api_key": "...",
|
|
112
121
|
"mistral_api_key": "...",
|
|
113
122
|
"modal_api_key": "sk-modal-..."
|
|
@@ -143,33 +152,23 @@ NVIDIA's API lists 130+ models, but 57+ return 404 "Function not found" when you
|
|
|
143
152
|
- **Auto-discovery from NVIDIA's API** — Queries `integrate.api.nvidia.com/v1/models` directly for the ground-truth list
|
|
144
153
|
- **`/probe-nvidia` command** — On-demand health check: tests every model with a minimal request, auto-hides new 404s, and re-registers immediately
|
|
145
154
|
|
|
146
|
-
### 🌩️ Cloudflare: Dynamic Model Discovery
|
|
147
|
-
|
|
148
|
-
Cloudflare Workers AI offers 80+ models including embeddings, image generation, and speech. pi-free automatically finds the chat models:
|
|
149
|
-
|
|
150
|
-
- **Live API fetching** — Calls Cloudflare's `/ai/models` endpoint on startup to get the current catalog
|
|
151
|
-
- **Smart filtering** — Automatically excludes embeddings (`bge-*`, `embed-*`), image generation (`flux`, `stable-diffusion`), speech (`whisper`, `aura-*`), translation, and vision-only models via regex patterns
|
|
152
|
-
- **Metadata inference** — Detects vision support (`llava`, `vision` in name), reasoning (`r1`, `thinking`, `qwq`), context windows, and estimated costs from model IDs
|
|
153
|
-
- **Expanding fallback** — 18 hand-curated models (Kimi K2.6, GPT-OSS, Qwen 2.5 Coder, QwQ, Llama 3.2 Vision, etc.) if API is unreachable
|
|
154
|
-
|
|
155
155
|
### 🎯 Coding Index (CI) Scores
|
|
156
156
|
|
|
157
157
|
Every model shows a **Coding Index score** (e.g., `CI: 52.3`) in the model picker:
|
|
158
158
|
|
|
159
159
|
- **Benchmark-based** — Scores derived from Artificial Analysis coding benchmarks (HumanEval, MBPP, etc.)
|
|
160
160
|
- **Quality indicator** — Higher scores = better coding performance
|
|
161
|
-
- **All providers** — Applied to every model from every provider (NVIDIA,
|
|
161
|
+
- **All providers** — Applied to every model from every provider (NVIDIA, Mistral, Groq, etc.)
|
|
162
162
|
|
|
163
163
|
**Missing CI scores?** Provider model IDs often don't match benchmark database keys exactly. pi-free applies provider-specific normalization to improve matching:
|
|
164
164
|
|
|
165
|
-
| Provider
|
|
166
|
-
|
|
|
167
|
-
| **NVIDIA**
|
|
168
|
-
| **
|
|
169
|
-
| **
|
|
170
|
-
| **
|
|
171
|
-
| **
|
|
172
|
-
| **Ollama** | Converts `model:tag` → `model-tag` |
|
|
165
|
+
| Provider | Normalization Applied |
|
|
166
|
+
| ------------ | ------------------------------------------------------------------ |
|
|
167
|
+
| **NVIDIA** | Strips vendor prefixes (`meta/`, `mistralai/`, `microsoft/`, etc.) |
|
|
168
|
+
| **Groq** | Removes `-versatile` and numeric suffixes (`-32768`) |
|
|
169
|
+
| **Cerebras** | Normalizes `llama3.1` → `llama-3.1`, adds `instruct` suffix |
|
|
170
|
+
| **Mistral** | Strips `-latest` suffix |
|
|
171
|
+
| **Ollama** | Converts `model:tag` → `model-tag` |
|
|
173
172
|
|
|
174
173
|
**Debug missing scores:** Check `~/.pi/modelmatch.log` to see which models matched/didn't match and what normalization was applied.
|
|
175
174
|
|
|
@@ -185,7 +184,7 @@ Providers have different pricing models. pi-free handles them all:
|
|
|
185
184
|
**Provider types:**
|
|
186
185
|
|
|
187
186
|
- ✅ **Free providers** (OpenCode, Kilo, Cline) — Toggle between free-only vs paid models
|
|
188
|
-
- 🔄 **Freemium** (NVIDIA,
|
|
187
|
+
- 🔄 **Freemium** (NVIDIA, Ollama) — Free tier with limits, toggle shows all
|
|
189
188
|
- 🔧 **Dynamic API** (Mistral, Groq, Cerebras, xAI) — Fetched when API key configured, toggle filters the list
|
|
190
189
|
|
|
191
190
|
### 🔐 OAuth + API Key Handling
|
|
@@ -314,61 +313,8 @@ Or in `~/.pi/free.json`:
|
|
|
314
313
|
|
|
315
314
|
Toggle anytime with `/toggle-nvidia`
|
|
316
315
|
|
|
317
|
-
### Cloudflare Workers AI (10K Neurons/day Free Tier)
|
|
318
|
-
|
|
319
|
-
Cloudflare provides **30+ text generation models** (auto-discovered from their API) with a generous free tier:
|
|
320
|
-
|
|
321
|
-
- **10,000 Neurons per day FREE** (resets daily at 00:00 UTC)
|
|
322
|
-
- **$0.011 per 1,000 Neurons** beyond the free allocation
|
|
323
|
-
- **Models auto-fetched** — All available chat models are discovered dynamically from Cloudflare's API
|
|
324
|
-
|
|
325
|
-
Get your API token at [dash.cloudflare.com/profile/api-tokens](https://dash.cloudflare.com/profile/api-tokens):
|
|
326
|
-
|
|
327
|
-
1. Create a token with "Cloudflare AI" → "Read" permission
|
|
328
|
-
2. Or use "My Account" → "Read" for broader access
|
|
329
|
-
|
|
330
|
-
**Setup:**
|
|
331
|
-
|
|
332
|
-
```bash
|
|
333
|
-
# New short env vars (recommended)
|
|
334
|
-
export CF_API_TOKEN="your_token_here"
|
|
335
|
-
export CF_ACCOUNT_ID="your_account_id"
|
|
336
|
-
|
|
337
|
-
# Legacy env vars also work
|
|
338
|
-
export CLOUDFLARE_API_TOKEN="your_token_here"
|
|
339
|
-
export CLOUDFLARE_ACCOUNT_ID="your_account_id"
|
|
340
|
-
```
|
|
341
|
-
|
|
342
316
|
**Models available:** Llama 4/3.x, Mistral Small 3.1, DeepSeek R1, Gemma 4, Kimi K2.5/2.6, Qwen 3/2.5, OpenAI GPT-OSS, and more.
|
|
343
317
|
|
|
344
|
-
Toggle with `/toggle-cloudflare`
|
|
345
|
-
|
|
346
|
-
### Modal (GLM-5.1 FP8 — free promotional period until April 30, 2026)
|
|
347
|
-
|
|
348
|
-
Modal hosts GLM-5.1 FP8 with a free promotional period. Get an API key at [modal.com](https://modal.com), then:
|
|
349
|
-
|
|
350
|
-
**Option A: Environment variable**
|
|
351
|
-
|
|
352
|
-
```bash
|
|
353
|
-
export MODAL_API_KEY="sk-modal-..."
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
**Option B: Config file** (`~/.pi/free.json`)
|
|
357
|
-
|
|
358
|
-
```json
|
|
359
|
-
{
|
|
360
|
-
"modal_api_key": "sk-modal-..."
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
Then select a `modal/` model in the model picker.
|
|
365
|
-
|
|
366
|
-
**Details:**
|
|
367
|
-
|
|
368
|
-
- Free promotional period until April 30, 2026
|
|
369
|
-
- Model: GLM-5.1 FP8 (128k context, 16k max output)
|
|
370
|
-
- No credit card required during the promotional period
|
|
371
|
-
|
|
372
318
|
### Ollama Cloud
|
|
373
319
|
|
|
374
320
|
Get an API key from [ollama.com/settings/keys](https://ollama.com/settings/keys), then:
|
|
@@ -407,18 +353,22 @@ export MISTRAL_API_KEY="..."
|
|
|
407
353
|
|
|
408
354
|
Each provider has toggle commands to switch between free and all models:
|
|
409
355
|
|
|
410
|
-
| Command
|
|
411
|
-
|
|
|
412
|
-
| `/toggle-opencode`
|
|
413
|
-
| `/toggle-kilo`
|
|
414
|
-
| `/toggle-openrouter`
|
|
415
|
-
| `/toggle-cline`
|
|
416
|
-
| `/toggle-nvidia`
|
|
417
|
-
| `/toggle-
|
|
418
|
-
| `/toggle-
|
|
419
|
-
| `/toggle-
|
|
420
|
-
| `/toggle-
|
|
421
|
-
| `/toggle-
|
|
356
|
+
| Command | Action |
|
|
357
|
+
| --------------------- | -------------------------------------------------------- |
|
|
358
|
+
| `/toggle-opencode` | Toggle between free/all OpenCode models |
|
|
359
|
+
| `/toggle-kilo` | Toggle between free/all Kilo models |
|
|
360
|
+
| `/toggle-openrouter` | Toggle between free/all OpenRouter models |
|
|
361
|
+
| `/toggle-cline` | Toggle between free/all Cline models |
|
|
362
|
+
| `/toggle-nvidia` | Toggle between free/all NVIDIA models |
|
|
363
|
+
| `/toggle-ollama` | Toggle between free/all Ollama Cloud models |
|
|
364
|
+
| `/toggle-mistral` | Toggle between free/all Mistral models (🔧 dynamic) |
|
|
365
|
+
| `/toggle-groq` | Toggle between free/all Groq models (🔧 dynamic) |
|
|
366
|
+
| `/toggle-cerebras` | Toggle between free/all Cerebras models (🔧 dynamic) |
|
|
367
|
+
| `/toggle-xai` | Toggle between free/all xAI models (🔧 dynamic) |
|
|
368
|
+
| `/toggle-huggingface` | Toggle between free/all Hugging Face models (🔧 dynamic) |
|
|
369
|
+
|
|
370
|
+
/toggle-zenmux # Toggle ZenMux (💳 paid - needs API key with credits)
|
|
371
|
+
/toggle-crofai # Toggle CrofAI (💳 paid - needs API key with credits)
|
|
422
372
|
|
|
423
373
|
**The toggle command:**
|
|
424
374
|
|
|
@@ -457,13 +407,10 @@ Create `~/.pi/free.json` in your home directory:
|
|
|
457
407
|
{
|
|
458
408
|
"openrouter_api_key": "YOUR_OPENROUTER_KEY",
|
|
459
409
|
"nvidia_api_key": "YOUR_NVIDIA_KEY",
|
|
460
|
-
"cloudflare_api_token": "YOUR_CLOUDFLARE_TOKEN",
|
|
461
|
-
"cloudflare_account_id": "YOUR_ACCOUNT_ID",
|
|
462
410
|
"mistral_api_key": "YOUR_MISTRAL_KEY",
|
|
463
411
|
"opencode_api_key": "YOUR_OPENCODE_KEY",
|
|
464
412
|
"ollama_api_key": "YOUR_OLLAMA_KEY",
|
|
465
413
|
"ollama_show_paid": true,
|
|
466
|
-
"modal_api_key": "YOUR_MODAL_KEY",
|
|
467
414
|
"hidden_models": ["model-id-to-hide"]
|
|
468
415
|
}
|
|
469
416
|
```
|
package/config.ts
CHANGED
|
@@ -24,54 +24,45 @@ const _logger = createLogger("config");
|
|
|
24
24
|
|
|
25
25
|
interface PiFreeConfig {
|
|
26
26
|
nvidia_api_key?: string;
|
|
27
|
-
cloudflare_api_token?: string;
|
|
28
|
-
cloudflare_account_id?: string;
|
|
29
27
|
ollama_api_key?: string;
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
zenmux_api_key?: string;
|
|
29
|
+
crofai_api_key?: string;
|
|
32
30
|
mistral_api_key?: string;
|
|
33
31
|
groq_api_key?: string;
|
|
34
32
|
cerebras_api_key?: string;
|
|
35
33
|
xai_api_key?: string;
|
|
36
34
|
hf_token?: string;
|
|
37
|
-
openrouter_api_key?: string;
|
|
38
35
|
kilo_free_only?: boolean;
|
|
39
36
|
hidden_models?: string[];
|
|
40
37
|
free_only?: boolean;
|
|
41
38
|
kilo_show_paid?: boolean;
|
|
42
|
-
nvidia_show_paid?: boolean;
|
|
43
|
-
cloudflare_show_paid?: boolean;
|
|
44
39
|
ollama_show_paid?: boolean;
|
|
45
40
|
cline_show_paid?: boolean;
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
zenmux_show_paid?: boolean;
|
|
42
|
+
crofai_show_paid?: boolean;
|
|
48
43
|
openrouter_show_paid?: boolean;
|
|
49
44
|
opencode_show_paid?: boolean;
|
|
50
45
|
}
|
|
51
46
|
|
|
52
47
|
const CONFIG_TEMPLATE: PiFreeConfig = {
|
|
53
48
|
nvidia_api_key: "",
|
|
54
|
-
cloudflare_api_token: "",
|
|
55
|
-
cloudflare_account_id: "",
|
|
56
49
|
ollama_api_key: "",
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
zenmux_api_key: "",
|
|
51
|
+
crofai_api_key: "",
|
|
59
52
|
mistral_api_key: "",
|
|
60
53
|
groq_api_key: "",
|
|
61
54
|
cerebras_api_key: "",
|
|
62
55
|
xai_api_key: "",
|
|
63
56
|
hf_token: "",
|
|
64
|
-
|
|
57
|
+
|
|
65
58
|
kilo_free_only: false,
|
|
66
59
|
hidden_models: [],
|
|
67
60
|
free_only: true,
|
|
68
61
|
kilo_show_paid: false,
|
|
69
|
-
nvidia_show_paid: false,
|
|
70
|
-
cloudflare_show_paid: false,
|
|
71
62
|
ollama_show_paid: false,
|
|
72
63
|
cline_show_paid: false,
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
zenmux_show_paid: false,
|
|
65
|
+
crofai_show_paid: false,
|
|
75
66
|
openrouter_show_paid: false,
|
|
76
67
|
opencode_show_paid: false,
|
|
77
68
|
};
|
|
@@ -144,34 +135,22 @@ export function getKiloShowPaid(): boolean {
|
|
|
144
135
|
return resolveBool("KILO_SHOW_PAID", loadConfigFile().kilo_show_paid);
|
|
145
136
|
}
|
|
146
137
|
|
|
147
|
-
export function getNvidiaShowPaid(): boolean {
|
|
148
|
-
return resolveBool("NVIDIA_SHOW_PAID", loadConfigFile().nvidia_show_paid);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
138
|
export function getClineShowPaid(): boolean {
|
|
152
139
|
return resolveBool("CLINE_SHOW_PAID", loadConfigFile().cline_show_paid);
|
|
153
140
|
}
|
|
154
141
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return resolveBool("QWEN_SHOW_PAID", loadConfigFile().qwen_show_paid);
|
|
142
|
+
export function getZenmuxShowPaid(): boolean {
|
|
143
|
+
return resolveBool("ZENMUX_SHOW_PAID", loadConfigFile().zenmux_show_paid);
|
|
158
144
|
}
|
|
159
145
|
|
|
160
|
-
export function
|
|
161
|
-
return resolveBool("
|
|
146
|
+
export function getCrofaiShowPaid(): boolean {
|
|
147
|
+
return resolveBool("CROFAI_SHOW_PAID", loadConfigFile().crofai_show_paid);
|
|
162
148
|
}
|
|
163
149
|
|
|
164
150
|
export function getOllamaShowPaid(): boolean {
|
|
165
151
|
return resolveBool("OLLAMA_SHOW_PAID", loadConfigFile().ollama_show_paid);
|
|
166
152
|
}
|
|
167
153
|
|
|
168
|
-
export function getCloudflareShowPaid(): boolean {
|
|
169
|
-
return resolveBool(
|
|
170
|
-
"CLOUDFLARE_SHOW_PAID",
|
|
171
|
-
loadConfigFile().cloudflare_show_paid,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
154
|
export function getOpenrouterShowPaid(): boolean {
|
|
176
155
|
return resolveBool(
|
|
177
156
|
"OPENROUTER_SHOW_PAID",
|
|
@@ -203,27 +182,16 @@ export function getNvidiaApiKey(): string | undefined {
|
|
|
203
182
|
return resolve("NVIDIA_API_KEY", loadConfigFile().nvidia_api_key);
|
|
204
183
|
}
|
|
205
184
|
|
|
206
|
-
export function
|
|
207
|
-
return resolve("
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export function getOllamaApiKey(): string | undefined {
|
|
211
|
-
return resolve("OLLAMA_API_KEY", loadConfigFile().ollama_api_key);
|
|
185
|
+
export function getZenmuxApiKey(): string | undefined {
|
|
186
|
+
return resolve("ZENMUX_API_KEY", loadConfigFile().zenmux_api_key);
|
|
212
187
|
}
|
|
213
188
|
|
|
214
|
-
export function
|
|
215
|
-
return resolve("
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
export function getCloudflareAccountId(): string | undefined {
|
|
219
|
-
return resolve(
|
|
220
|
-
"CLOUDFLARE_ACCOUNT_ID",
|
|
221
|
-
loadConfigFile().cloudflare_account_id,
|
|
222
|
-
);
|
|
189
|
+
export function getCrofaiApiKey(): string | undefined {
|
|
190
|
+
return resolve("CROFAI_API_KEY", loadConfigFile().crofai_api_key);
|
|
223
191
|
}
|
|
224
192
|
|
|
225
|
-
export function
|
|
226
|
-
return resolve("
|
|
193
|
+
export function getOllamaApiKey(): string | undefined {
|
|
194
|
+
return resolve("OLLAMA_API_KEY", loadConfigFile().ollama_api_key);
|
|
227
195
|
}
|
|
228
196
|
|
|
229
197
|
export function getMistralApiKey(): string | undefined {
|
|
@@ -246,8 +214,12 @@ export function getHfToken(): string | undefined {
|
|
|
246
214
|
return resolve("HF_TOKEN", loadConfigFile().hf_token);
|
|
247
215
|
}
|
|
248
216
|
|
|
217
|
+
/**
|
|
218
|
+
* OpenRouter key — pi's built-in provider reads from ~/.pi/agent/auth.json.
|
|
219
|
+
* pi-free only checks the env var to avoid stale keys from free.json.
|
|
220
|
+
*/
|
|
249
221
|
export function getOpenrouterApiKey(): string | undefined {
|
|
250
|
-
return
|
|
222
|
+
return process.env.OPENROUTER_API_KEY;
|
|
251
223
|
}
|
|
252
224
|
|
|
253
225
|
// =============================================================================
|
package/constants.ts
CHANGED
|
@@ -15,6 +15,8 @@ export const PROVIDER_OLLAMA = "ollama-cloud";
|
|
|
15
15
|
/** @deprecated Qwen provider is deprecated. The 1,000 req/day free tier is no longer available. */
|
|
16
16
|
export const PROVIDER_QWEN = "qwen";
|
|
17
17
|
export const PROVIDER_MODAL = "modal";
|
|
18
|
+
export const PROVIDER_ZENMUX = "zenmux";
|
|
19
|
+
export const PROVIDER_CROFAI = "crofai";
|
|
18
20
|
|
|
19
21
|
export const ALL_UNIQUE_PROVIDERS = [
|
|
20
22
|
PROVIDER_KILO,
|
|
@@ -24,6 +26,8 @@ export const ALL_UNIQUE_PROVIDERS = [
|
|
|
24
26
|
PROVIDER_QWEN,
|
|
25
27
|
PROVIDER_MODAL,
|
|
26
28
|
PROVIDER_OLLAMA,
|
|
29
|
+
PROVIDER_ZENMUX,
|
|
30
|
+
PROVIDER_CROFAI,
|
|
27
31
|
] as const;
|
|
28
32
|
|
|
29
33
|
// =============================================================================
|
|
@@ -38,6 +42,8 @@ export const BASE_URL_CLINE = "https://api.cline.bot/api/v1";
|
|
|
38
42
|
export const BASE_URL_MODAL = "https://api.us-west-2.modal.direct/v1";
|
|
39
43
|
export const BASE_URL_QWEN =
|
|
40
44
|
"https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
45
|
+
export const BASE_URL_ZENMUX = "https://zenmux.ai/api/v1";
|
|
46
|
+
export const BASE_URL_CROFAI = "https://crof.ai/v1";
|
|
41
47
|
|
|
42
48
|
/** Cline fetches free models from OpenRouter */
|
|
43
49
|
export const BASE_URL_OPENROUTER = "https://openrouter.ai/api/v1";
|