pi-freeflow 1.33.3 → 1.35.0
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 +66 -0
- package/README.md +67 -35
- package/package.json +1 -1
- package/src/catalog.ts +30 -3
- package/src/cline-accounts.ts +15 -13
- package/src/config.ts +11 -0
- package/src/index.ts +3 -3
- package/src/models.ts +233 -85
- package/src/opencode-fingerprint.ts +143 -16
- package/src/proxy.ts +188 -13
- package/src/tool-args.ts +48 -9
- package/src/tool-translation.ts +112 -33
- package/src/types.ts +162 -162
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.35.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9085408: Nine more free models, from OVHcloud's AI Endpoints — and no account needed
|
|
8
|
+
|
|
9
|
+
The picker now offers nine open-weight models served by OVHcloud AI Endpoints, bringing the catalog to 36: GPT-OSS 120B and 20B, four Qwen models (3.5 397B, 3.5 9B, 3.6 27B, 3.8 27B), Mistral Small 3.2 and Mistral 7B, and Meta Llama 3.3 70B. The four Qwens and Mistral Small 3.2 also read images.
|
|
10
|
+
|
|
11
|
+
Access is anonymous and keyless. There is nothing to sign up for and no key to paste — no login step, no saved credential, no setup of any kind. Pick a model and it works.
|
|
12
|
+
|
|
13
|
+
The honest caveat: OVH rate-limits anonymous callers per IP address. A burst of parallel subagents can run into `API rate limit exceeded`, the same way a shared OpenCode or Kilo quota does. Wait it out or spread the work across models. Requests to these models always go straight to OVH from your machine, never through your relay pool — there is no per-IP gate for a relay to route around.
|
|
14
|
+
|
|
15
|
+
Thinking depth is limited to the two levels OVH confirms, `low` and `high`, on the six models that reason. The output budgets are deliberately conservative: they are the smallest cap any provider offers for the same underlying model, so a turn never asks for more than OVH will give.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 3408dad: Stop conversations from dying on request shapes the provider rejects
|
|
20
|
+
|
|
21
|
+
Three shapes that the provider answers with `400 invalid parameters` are now reshaped on the way out instead of failing the whole turn.
|
|
22
|
+
|
|
23
|
+
- **A model narrates a tool call instead of making one.** The reply is recorded as pre-tool commentary, and every later message replayed that turn back to the provider was rejected — the session could not continue or be resumed, because each retry sent the same history again.
|
|
24
|
+
- **A host asks for a specific tool or forces a tool call.** The free provider accepts only automatic tool selection, so an unsupported choice is dropped rather than sent. Nothing is imposed on a host that did not ask.
|
|
25
|
+
- **A tool name carries a character the provider rejects.** Spaces, colons and slashes are folded for the trip out and the caller's own name is restored on the way back, so the tool still runs under the name it was registered with. Names that are already accepted are sent exactly as they always were.
|
|
26
|
+
|
|
27
|
+
Measured on Muse Spark 1.3: the same three requests that each failed with an error now answer normally, and a well-formed tool set reaches the model byte-identical to before.
|
|
28
|
+
|
|
29
|
+
- 9085408: Three free models that no longer answer are gone from the picker
|
|
30
|
+
|
|
31
|
+
`cline-free/deepseek-v4.1-flash`, `cline-free/kimi-k3` and `cline-free/solar-pro4` were retired upstream, so every turn on them failed. All three were probed twice against the live service on 2026-10-13 and each time answered `404 model not found` ("Cline has no such model. Refresh the model list and retry."), while the two Cline models that survive — `cline-free/muse-spark-1.3-contributor` and `z-ai/glm-5.3-flash` — answered 200 with the same login and request shape. The login, the quota rollover and every other model are unchanged; the picker is now 36 models (10 OpenCode, 15 Kilo, 2 Cline, 9 OVH).
|
|
32
|
+
|
|
33
|
+
## 1.34.0
|
|
34
|
+
|
|
35
|
+
### Minor Changes
|
|
36
|
+
|
|
37
|
+
- aa6f259: Three new free models, picked the same way as the rest (`/model` → `freeflow` → pick):
|
|
38
|
+
|
|
39
|
+
- **Step 5 Preview** on OpenCode Zen (`step-5-preview-free`, short name `step-5-preview`) — 1M context, answers with vision.
|
|
40
|
+
- **Step 5 Preview** on KiloCode (`stepfun/step-5-preview-free`, short name `step-5-preview:kilo`) — 1M context, answers with vision.
|
|
41
|
+
- **Glyph Cluster** on KiloCode (`stealth/glyph-cluster`, short name `glyph-cluster`) — 256K context, text answers.
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- 50981fb: Align nine model entries with the specs their upstream catalogs publish. Models now advertise video input where the vendor lists it, two entries pick up a larger context window, and Step 5 Preview on KiloCode reports the full 64K output allowance.
|
|
46
|
+
- f637c58: Recover tool calls that arrive with the tail of the previous call stuck to the
|
|
47
|
+
front. Some models open a new call by echoing the end of the one they have just
|
|
48
|
+
seen, so a single call is delivered as `<tail of previous>{"…this call…"}` and
|
|
49
|
+
the host refuses it as invalid JSON. When such a payload does not parse, the
|
|
50
|
+
proxy now locates the complete call behind the stray text and hands that back.
|
|
51
|
+
|
|
52
|
+
Only payloads that already fail to parse are rescanned, and only a position that
|
|
53
|
+
yields a complete object is accepted — a well-formed call is never rewritten,
|
|
54
|
+
and a truncated one is still refused rather than completed.
|
|
55
|
+
|
|
56
|
+
Also adds a whole-inventory fidelity test covering every tool either host can
|
|
57
|
+
declare, across all three API shapes.
|
|
58
|
+
|
|
59
|
+
- aa6f259: Remove three free models that stopped serving upstream, so they no longer appear in the model list:
|
|
60
|
+
|
|
61
|
+
- **Fledge Alpha** on OpenCode (`fledge-alpha-free`) — withdrawn upstream and no longer listed.
|
|
62
|
+
- **Ling 3.0 Flash Sante** on KiloCode (`inclusionai/ling-3.0-flash-sante:free`) — the free variant is gone; only the paid one remains.
|
|
63
|
+
- **Step 3.7 Flash** on KiloCode (`stepfun/step-3.7-flash:free`) — the free variant is gone; only the paid one remains.
|
|
64
|
+
|
|
65
|
+
All three are excluded permanently, so a stale on-disk catalog or a later catalog refresh cannot bring them back.
|
|
66
|
+
|
|
67
|
+
- 50981fb: Correct the OpenCode Zen Step 5 Preview entry: it is a reasoning model with 1M context, 64K max output, text/image/video input, and only `low`/`medium`/`high` thinking levels (`minimal` is explicitly disabled). Previously the entry mirrored the Kilo sibling and the fallback heuristic, so the picker showed no thinking support.
|
|
68
|
+
|
|
3
69
|
## 1.33.3
|
|
4
70
|
|
|
5
71
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-freeflow
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 36 free models with up to 1M context. No API keys to manage. Add your own relays to spread requests across more IPs.
|
|
4
4
|
|
|
5
5
|
Thin by design: a model list, a relay proxy, and a log. The host (`pi-ai`) handles thinking, normalization, and provider behavior.
|
|
6
6
|
|
|
@@ -16,10 +16,10 @@ Thin by design: a model list, a relay proxy, and a log. The host (`pi-ai`) handl
|
|
|
16
16
|
|
|
17
17
|
| Feature | What it does | Cost |
|
|
18
18
|
| :--- | :--- | :--- |
|
|
19
|
-
| **
|
|
20
|
-
| **Relay pool** | Route requests through your own Cloudflare Workers and Vercel Edge relays. Traffic spreads across the pool, or stays on one sticky relay. A relay that rate-limits, times out, or drops the connection cools down while healthy ones take its traffic. | **$0** beyond your platforms' free tiers |
|
|
19
|
+
| **36 free models** | 10 from OpenCode Zen, 15 from KiloCode Gateway, 2 from Cline, 9 from OVHcloud AI Endpoints, context windows up to 1M. Full list below. | **$0** |
|
|
20
|
+
| **Relay pool** | Route requests through your own Cloudflare Workers, Deno Deploy, and Vercel Edge relays. Traffic spreads across the pool, or stays on one sticky relay. A relay that rate-limits, times out, or drops the connection cools down while healthy ones take its traffic. | **$0** beyond your platforms' free tiers |
|
|
21
21
|
| **Automatic fallback** | When every relay is cooling down, requests go direct to upstream instead of failing. | **$0** |
|
|
22
|
-
| **Short model names** |
|
|
22
|
+
| **Short model names** | Most models have a slash-free, colon-free alias, plus an optional `:effort` suffix for thinking depth. You type `freeflow/<name>`; the two Cline models have no alias and must be typed in full. | **$0** |
|
|
23
23
|
| **Shared local proxy** | One daemon on `127.0.0.1:28180` serves every session on the machine, so parallel subagents reuse it instead of opening their own connections. | **$0** |
|
|
24
24
|
| **Logs you can read** | `~/.pi/agent/pi-freeflow.log`, rotated at 10MB. Tail it with `/freeflow logs`. | **$0** |
|
|
25
25
|
|
|
@@ -85,7 +85,7 @@ Manual fallback per platform:
|
|
|
85
85
|
**Option A: Cloudflare Workers, auto deploy (recommended)**
|
|
86
86
|
```bash
|
|
87
87
|
/freeflow deploy cloudflare # prompts token in-memory, auto-adds to pool
|
|
88
|
-
# or
|
|
88
|
+
# or /freeflow deploy with no argument to pick the platform interactively
|
|
89
89
|
```
|
|
90
90
|
Manual fallback: `dash.cloudflare.com` → Workers → Create → Deploy → Edit code → paste the canonical worker source (see below) → Deploy → `/freeflow add https://your.workers.dev cf-worker-1`
|
|
91
91
|
|
|
@@ -110,7 +110,7 @@ For `api/relay.js`, use the canonical worker source (see below); `vercel.json` s
|
|
|
110
110
|
|
|
111
111
|
**Canonical worker source (all platforms)**
|
|
112
112
|
|
|
113
|
-
The relay worker template is generated per deployment by `/freeflow deploy`, with one shared core adapted for Vercel, Cloudflare, and Deno.
|
|
113
|
+
The relay worker template is generated per deployment by `/freeflow deploy`, with one shared core adapted for Vercel, Cloudflare, and Deno. Every deploy embeds a random 32-byte secret, and the generated worker answers `401` to any request without a matching `x-relay-auth` header; the client sends that secret to each relay in the pool. Only a hand-pasted legacy worker built without a secret is open to anyone. Either way, a relay forwards only to an allowlist (`https://opencode.ai`, `https://api.kilo.ai`) with private-host and path checks.
|
|
114
114
|
|
|
115
115
|
```js
|
|
116
116
|
// Minimal Cloudflare illustration. Prefer /freeflow deploy: the generated
|
|
@@ -185,7 +185,7 @@ The same command set works identically in OMP and Pi:
|
|
|
185
185
|
|
|
186
186
|
---
|
|
187
187
|
|
|
188
|
-
###
|
|
188
|
+
### 36 models, one command
|
|
189
189
|
|
|
190
190
|
```bash
|
|
191
191
|
/model → freeflow → pick
|
|
@@ -205,10 +205,10 @@ Good defaults for long coding sessions and agentic work.
|
|
|
205
205
|
| `big-pickle` | Big Pickle | **200K** (200.000) | **32K** (32.000) | `high / max` | ❌ |
|
|
206
206
|
| `space-bunny-free` | Stealth preview (lab undisclosed) | **1M** (1.048.576) | **512K** (524.288) | `low … max` | ✅ |
|
|
207
207
|
| `longcat-2.5-preview-free` | Meituan LongCat | **1M** (1.000.000) | **131K** (131.072) | `minimal … max` | ✅ |
|
|
208
|
-
| `
|
|
208
|
+
| `step-5-preview-free` | StepFun | **1M** (1.000.000) | **64K** (65.536) | `low … high` | ✅ |
|
|
209
209
|
| `ling-3.1-flash-free` | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal … max` | ❌ |
|
|
210
210
|
|
|
211
|
-
#### KiloCode Gateway (
|
|
211
|
+
#### KiloCode Gateway (15 models), OpenRouter compatible
|
|
212
212
|
|
|
213
213
|
Keyless access. Short aliases work for every row (the full ID is in parentheses).
|
|
214
214
|
|
|
@@ -225,14 +225,14 @@ Keyless access. Short aliases work for every row (the full ID is in parentheses)
|
|
|
225
225
|
| `lfm-2.5` (`liquid/lfm-2.5-2.6b:free`) | Liquid AI | **65K** (65.536) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
|
|
226
226
|
| `kilo-auto` (`kilo-auto/free`) | Kilo Gateway Auto | **256K** (256.000) | **10K** (10.000) | `minimal…xhigh`\* | ❌ |
|
|
227
227
|
| `openrouter` (`openrouter/free`) | OpenRouter Free | **200K** (200.000) | **65K** (65.536) | `minimal…xhigh`\* | ✅ |
|
|
228
|
-
| `
|
|
229
|
-
| `step-
|
|
228
|
+
| `glyph-cluster` (`stealth/glyph-cluster`) | Stealth preview (lab undisclosed) | **256K** (256.000) | **256K** (256.000) | `minimal…xhigh`\* | ❌ |
|
|
229
|
+
| `step-5-preview:kilo` (`stepfun/...:free`) | StepFun | **1M** (1.000.000) | **64K** (65.536) | `minimal…xhigh`\* | ✅ |
|
|
230
230
|
| `inkling-small` (`thinkingmachines/inkling-small:free`) | Thinking Machines | **1M** (1.048.576) | **262K** (262.144) | `minimal…xhigh`\* | ✅ |
|
|
231
|
-
| `ling-3.1-flash
|
|
231
|
+
| `ling-3.1-flash:kilo` (`inclusionai/ling-3.1-flash`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
|
|
232
232
|
|
|
233
233
|
\* Levels are forwarded as-is through the OpenRouter-style nested `reasoning` parameter; effort mapping is decided by each model. MiMo collapses `minimal→low` and `xhigh→high` upstream, so its selector shows 5 labels but only 3 distinct effort values.
|
|
234
234
|
|
|
235
|
-
#### Cline (
|
|
235
|
+
#### Cline (2 models), OpenAI compatible
|
|
236
236
|
|
|
237
237
|
Rotating per-account promo, direct only (never through the relay pool). Sign in through your browser with `/freeflow cline login`, manage with `/freeflow cline accounts` and `/freeflow cline logout`. Requests roll across saved logins when one hits its daily free limit.
|
|
238
238
|
|
|
@@ -242,11 +242,28 @@ Each account can only be saved once: an extra login for an account you already h
|
|
|
242
242
|
|
|
243
243
|
| Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
|
|
244
244
|
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
245
|
-
| `cline-free/deepseek-v4.1-flash` | DeepSeek | **1M** (1.000.000) | **384K** (384.000) | `low/high/max` | ✅ |
|
|
246
245
|
| `cline-free/muse-spark-1.3-contributor` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal…xhigh`\* | ✅ |
|
|
247
|
-
| `z-ai/glm-5.3-flash` | Zhipu AI | **1M** (1.
|
|
248
|
-
|
|
249
|
-
|
|
246
|
+
| `z-ai/glm-5.3-flash` | Zhipu AI | **1M** (1.048.576) | **131K** (131.072) | `low/high/max` | ✅ |
|
|
247
|
+
|
|
248
|
+
#### OVHcloud AI Endpoints (9 models), OpenAI compatible
|
|
249
|
+
|
|
250
|
+
Anonymous access — no account, no key, nothing to sign in to. Direct only (never through the relay pool), because OVH has no per-IP gate for relays to route around. OVH rate-limits anonymous callers per IP, so a burst of parallel subagents can hit `429 API rate limit exceeded`; the model list itself never costs anything.
|
|
251
|
+
|
|
252
|
+
Pick them with the slash-free short name (the full ID is in parentheses). Only `low` and `high` thinking levels are offered, because those are the two OVH confirmed.
|
|
253
|
+
|
|
254
|
+
All nine talk the normal chat API. Hosts that prefer the responses API work too — the proxy maps that shape to chat and maps the answer back, so tool calls and streamed output behave exactly as they do on the other providers.
|
|
255
|
+
|
|
256
|
+
| Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
|
|
257
|
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
258
|
+
| `gpt-oss-120b` (`ovh-free/gpt-oss-120b`) | OpenAI | **128K** (131.072) | **32K** (32.768) | `low/high` | ❌ |
|
|
259
|
+
| `gpt-oss-20b` (`ovh-free/gpt-oss-20b`) | OpenAI | **128K** (131.072) | **32K** (32.768) | `low/high` | ❌ |
|
|
260
|
+
| `qwen3.5-397b` (`ovh-free/Qwen3.5-397B-A17B`) | Alibaba Qwen | **256K** (262.144) | **64K** (65.536) | `low/high` | ✅ |
|
|
261
|
+
| `qwen3.5-9b` (`ovh-free/Qwen3.5-9B`) | Alibaba Qwen | **256K** (262.144) | **64K** (65.536) | `low/high` | ✅ |
|
|
262
|
+
| `qwen3.6-27b` (`ovh-free/Qwen3.6-27B`) | Alibaba Qwen | **256K** (262.144) | **64K** (65.536) | `low/high` | ✅ |
|
|
263
|
+
| `qwen3.8-27b` (`ovh-free/Qwen3.8-27B`) | Alibaba Qwen | **256K** (262.144) | **32K** (32.768) | `low/high` | ✅ |
|
|
264
|
+
| `mistral-small-3.2` (`ovh-free/Mistral-Small-3.2-24B-Instruct-2506`) | Mistral AI | **128K** (131.072) | **16K** (16.384) | ❌ | ✅ |
|
|
265
|
+
| `mistral-7b-v0.3` (`ovh-free/Mistral-7B-Instruct-v0.3`) | Mistral AI | **64K** (65.536) | **64K** (65.536) | ❌ | ❌ |
|
|
266
|
+
| `llama-3.3-70b` (`ovh-free/Meta-Llama-3_3-70B-Instruct`) | Meta | **128K** (131.072) | **16K** (16.384) | ❌ | ❌ |
|
|
250
267
|
|
|
251
268
|
---
|
|
252
269
|
|
|
@@ -264,16 +281,16 @@ cat ~/.pi/agent/pi-freeflow.log | tail -n 50
|
|
|
264
281
|
|
|
265
282
|
### Design
|
|
266
283
|
|
|
267
|
-
This package stays thin. It ships three things: a model catalog, a relay proxy, and a log. There is no build step and
|
|
284
|
+
This package stays thin. It ships three things: a model catalog, a relay proxy, and a log. There is no build step and one runtime dependency (`undici`). Thinking and prompt normalization stay with the host (`pi-ai`).
|
|
268
285
|
|
|
269
|
-
About
|
|
286
|
+
About 43k lines including tests: `src/` is roughly 17k across 27 files, and the 78 test files add roughly 26k more. The full suite (sandboxed, network-mocked) and typecheck pass before every release. See CHANGELOG.md.
|
|
270
287
|
|
|
271
288
|
---
|
|
272
289
|
|
|
273
290
|
### FAQ
|
|
274
291
|
|
|
275
292
|
**Do I need API keys?**
|
|
276
|
-
No. Kilo
|
|
293
|
+
No. OpenCode and Kilo free models are both keyless: the proxy sends no `Authorization` header at all, and a placeholder credential is rejected rather than merely unused — `Bearer kilo-free` answers `401 INVALID_TOKEN`, while sending nothing answers 200 for every free catalog model. You never paste a key. Cline free models need a browser login instead: `/freeflow cline login` saves it to a per-user pool on your machine. OVHcloud AI Endpoints models need no account and no key at all.
|
|
277
294
|
|
|
278
295
|
**What if all relays hit rate limits?**
|
|
279
296
|
The proxy tries direct upstream. If that is also rate-limited, the host shows the limit. That number is the shared upstream cap; without relays you would hit the same wall sooner.
|
|
@@ -340,27 +357,42 @@ pnpm smoke # verifies extensions/index.ts loads without crashing
|
|
|
340
357
|
|
|
341
358
|
```
|
|
342
359
|
src/
|
|
343
|
-
├── index.ts
|
|
344
|
-
├── models.ts
|
|
345
|
-
├── catalog.ts
|
|
346
|
-
├── proxy.ts
|
|
347
|
-
├──
|
|
348
|
-
├──
|
|
349
|
-
├──
|
|
350
|
-
├──
|
|
351
|
-
├──
|
|
352
|
-
├──
|
|
353
|
-
├──
|
|
354
|
-
|
|
360
|
+
├── index.ts # extension entry, lifecycle hooks
|
|
361
|
+
├── models.ts # 36-model catalog definitions
|
|
362
|
+
├── catalog.ts # model catalog cache (24h disk)
|
|
363
|
+
├── proxy.ts # local proxy server (127.0.0.1:28180)
|
|
364
|
+
├── client.ts # session-side daemon attach/spawn and heartbeat
|
|
365
|
+
├── daemon.ts # detached proxy daemon process (owns the port)
|
|
366
|
+
├── lease.ts # client lease registry and TTL retirement
|
|
367
|
+
├── health.ts # loopback /_health relay snapshot
|
|
368
|
+
├── responses.ts # Responses-API reasoning portability
|
|
369
|
+
├── tool-translation.ts # tool reshape across chat/responses/messages
|
|
370
|
+
├── tool-args.ts # schema-driven repair of model tool-call arguments
|
|
371
|
+
├── relay.ts # relay fetch, rolling on retryable failures
|
|
372
|
+
├── relay-state.ts # relay pool state, health tracking
|
|
373
|
+
├── probe.ts # relay reachability and latency probe
|
|
374
|
+
├── upstream-health.ts # Zen free-tier gating watch and Kilo failover
|
|
375
|
+
├── stream-pipe.ts # SSE stream piping and truncation resilience
|
|
376
|
+
├── opencode-fingerprint.ts # Zen free-tier client fingerprint enforcement
|
|
377
|
+
├── system-ca-fetch.ts # OS-trust-store retry for intercepted TLS
|
|
378
|
+
├── commands.ts # /freeflow CLI subcommands
|
|
379
|
+
├── deploy.ts # guided relay deploy (vercel/cloudflare/deno)
|
|
380
|
+
├── cline-accounts.ts # per-slot Cline key pool with failover
|
|
381
|
+
├── cline-device-auth.ts # Cline WorkOS device-flow login
|
|
382
|
+
├── update-checker.ts # npm registry version check, cached
|
|
383
|
+
├── updater.ts # package-manager choice for /freeflow update
|
|
384
|
+
├── config.ts # constants, whitelists, paths, and runtime settings
|
|
385
|
+
├── logger.ts # file logger with 10MB rotation
|
|
386
|
+
└── types.ts # shared type definitions
|
|
355
387
|
extensions/
|
|
356
|
-
└── index.ts
|
|
388
|
+
└── index.ts # OMP/Pi extension manifest
|
|
357
389
|
test/
|
|
358
|
-
└── *.test.ts
|
|
390
|
+
└── *.test.ts # mirrors src/, node:test runner
|
|
359
391
|
```
|
|
360
392
|
|
|
361
393
|
#### Guidelines
|
|
362
394
|
|
|
363
|
-
- **Stay thin.**
|
|
395
|
+
- **Stay thin.** One runtime dependency (`undici`), no build step. If it belongs in the host (`pi-ai`), don't add it here.
|
|
364
396
|
- **Test what you touch.** Every `src/*.ts` has a matching `test/*.test.ts`. Add or update tests for your change.
|
|
365
397
|
- **Keep model IDs clean.** Slash-free, colon-free aliases for CLI compatibility. See existing patterns in `models.ts`.
|
|
366
398
|
- **One concern per PR.** Bug fix? One PR. New relay platform? Separate PR. Easier to review, faster to merge.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-freeflow",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.35.0",
|
|
5
5
|
"description": "Thin provider for OMP/Pi — model list + dumb relay proxy + log; host pi-ai owns thinking/normalization",
|
|
6
6
|
"main": "extensions/index.ts",
|
|
7
7
|
"types": "src/index.ts",
|
package/src/catalog.ts
CHANGED
|
@@ -30,7 +30,8 @@ import type {
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Pruned model IDs that must never re-enter the catalog via disk cache or upstream merge.
|
|
33
|
-
* - jev-1.13-free: non-chat decision model, chat-incompatible
|
|
33
|
+
* - jev-1.13-free: non-chat decision model, chat-incompatible — never registered.
|
|
34
|
+
* Re-confirmed 2026-10-09: 400 through the plugin while every catalog model 200s.
|
|
34
35
|
* - deepseek-v4-flash-free: listed but unserved upstream (live chat 400 "Model is unavailable").
|
|
35
36
|
* - nex-agi/nex-n2.5-pro:free + nex-agi/nex-n2.5-mini:free: gone 2026-09-28 — zero nex-agi
|
|
36
37
|
* IDs on the live Kilo list, keyless chat 404 "does not exist".
|
|
@@ -43,7 +44,18 @@ import type {
|
|
|
43
44
|
* - inclusionai/ling-3.0-flash-fin:free: gone from Kilo (2026-10-01) — keyless chat 404
|
|
44
45
|
* "The requested model ... does not exist".
|
|
45
46
|
* - mimo-v2.5-free: decommissioned upstream (2026-10-07) — HTTP 401 "Model mimo-v2.5-free is not supported".
|
|
46
|
-
* - exo-free:
|
|
47
|
+
* - exo-free: deprecated upstream (2026-10-09) — HTTP 410 "Model exo-free has
|
|
48
|
+
* been deprecated." (was 503 "Endpoint is unavailable" on 2026-10-07).
|
|
49
|
+
* - fledge-alpha-free: withdrawn upstream (2026-10-09) — absent from the live
|
|
50
|
+
* Zen list, chat 401 "Model fledge-alpha-free is not supported".
|
|
51
|
+
* - inclusionai/ling-3.0-flash-sante:free: demoted to paid on Kilo (2026-10-09) —
|
|
52
|
+
* :free ID gone from the live list, keyless chat 404 "does not exist";
|
|
53
|
+
* only the paid counterpart remains.
|
|
54
|
+
* - stepfun/step-3.7-flash:free: demoted to paid on Kilo (2026-10-09) — same
|
|
55
|
+
* shape: :free ID gone, keyless 404; paid ID remains.
|
|
56
|
+
* - meituan/longcat-2.0-free: demoted to paid on Kilo (2026-10-09) —
|
|
57
|
+
* `meituan/longcat-2.0` remains live with isFree:false; keyless chat
|
|
58
|
+
* answers 401 PAID_MODEL_AUTH_REQUIRED.
|
|
47
59
|
* - stealth/space-bunny-alpha: gone from Kilo (2026-10-07) — keyless chat 404 "The requested model ... does not exist".
|
|
48
60
|
* - qwen/qwen3.8-27b:free: gone from Kilo (2026-10-07) — keyless chat 404 "The requested model is currently unavailable.".
|
|
49
61
|
* - nvidia/nemotron-3.5-content-safety:free: tool-less guardrail model (2026-10-08),
|
|
@@ -54,6 +66,15 @@ import type {
|
|
|
54
66
|
* and responses from LLMs", not a chat model. Same exclusion class as
|
|
55
67
|
* jev-1.13-free: live, wrong shape for an agentic harness, so it must never
|
|
56
68
|
* re-enter the picker via disk cache or upstream merge.
|
|
69
|
+
* - cline-free/deepseek-v4.1-flash, cline-free/kimi-k3, cline-free/solar-pro4:
|
|
70
|
+
* retired upstream (2026-10-13) — probed live twice each against the real
|
|
71
|
+
* Cline pool, every attempt answered HTTP 404 `{"error":"model not found",
|
|
72
|
+
* "success":false,"hint":"Cline has no such model. Refresh the model list and
|
|
73
|
+
* retry."}`, while the two Cline models that survive (cline-free/
|
|
74
|
+
* muse-spark-1.3-contributor and z-ai/glm-5.3-flash) answered 200 with the
|
|
75
|
+
* same account and request shape. The lane is healthy; these three ids are
|
|
76
|
+
* gone, so they must never re-enter the picker from disk cache or an
|
|
77
|
+
* upstream merge.
|
|
57
78
|
*/
|
|
58
79
|
export const DEAD_MODEL_IDS = new Set<string>([
|
|
59
80
|
"jev-1.13-free",
|
|
@@ -78,6 +99,12 @@ export const DEAD_MODEL_IDS = new Set<string>([
|
|
|
78
99
|
"stealth/space-bunny-alpha",
|
|
79
100
|
"qwen/qwen3.8-27b:free",
|
|
80
101
|
"nvidia/nemotron-3.5-content-safety:free",
|
|
102
|
+
"fledge-alpha-free",
|
|
103
|
+
"inclusionai/ling-3.0-flash-sante:free",
|
|
104
|
+
"stepfun/step-3.7-flash:free",
|
|
105
|
+
"cline-free/deepseek-v4.1-flash",
|
|
106
|
+
"cline-free/kimi-k3",
|
|
107
|
+
"cline-free/solar-pro4",
|
|
81
108
|
]);
|
|
82
109
|
/**
|
|
83
110
|
* Free-tier allowlist for anything entering the picker via network or stale disk.
|
|
@@ -117,7 +144,7 @@ export function sanitizeCatalogModels(models: RegisteredModel[]): RegisteredMode
|
|
|
117
144
|
}
|
|
118
145
|
/**
|
|
119
146
|
* In-memory cache of currently active/available free models.
|
|
120
|
-
* Initialized with all
|
|
147
|
+
* Initialized with all 36 verified models for 0ms instant availability.
|
|
121
148
|
*/
|
|
122
149
|
let aliveCatalog: RegisteredModel[] = ALL_MODELS.map((m) => ({
|
|
123
150
|
...m,
|
package/src/cline-accounts.ts
CHANGED
|
@@ -116,15 +116,17 @@ export const CLINE_CLIENT_VERSION = "3.5.54";
|
|
|
116
116
|
* mirror reference/cline providers/request-headers.ts
|
|
117
117
|
* (DEFAULT_CLINE_REQUEST_HEADERS) — no credential is derived from them.
|
|
118
118
|
*
|
|
119
|
-
* `X-CLIENT-TYPE` is the Cline desktop app's identity, and it
|
|
120
|
-
* free
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* the
|
|
119
|
+
* `X-CLIENT-TYPE` is the Cline desktop app's identity, and it gates the
|
|
120
|
+
* `cline-free/*` id space (measured live 2026-09-22: that prefix answers 403
|
|
121
|
+
* "only available via Cline product surfaces" with a bare bearer, and 200 with
|
|
122
|
+
* this set; every non-prefixed id answers 200 either way). The header is kept
|
|
123
|
+
* because one catalog id still depends on it — after the 2026-10-13 prune,
|
|
124
|
+
* `cline-free/muse-spark-1.3-contributor` is the last prefixed model in the
|
|
125
|
+
* catalog. It also decided the free-model feed at the time: five entries for
|
|
126
|
+
* `cline-sdk` / `cline-cli` / the `VSCode Extension` label against six for
|
|
127
|
+
* `cline-desktop`, the extra one being `cline-free/kimi-k3`. That sixth model
|
|
128
|
+
* is retired upstream and no longer requested. Version and User-Agent stay
|
|
129
|
+
* as-is: the feed served the desktop list with them unchanged.
|
|
128
130
|
*/
|
|
129
131
|
export const CLINE_CLIENT_HEADERS: Record<string, string> = {
|
|
130
132
|
"HTTP-Referer": "https://cline.bot",
|
|
@@ -138,12 +140,12 @@ export const CLINE_CLIENT_HEADERS: Record<string, string> = {
|
|
|
138
140
|
/**
|
|
139
141
|
* Free-limit report carried by a Cline 429 body, e.g.
|
|
140
142
|
* {"error":{"code":"INFERENCE_CAP_ERROR","message":"Error 429: Daily free limit
|
|
141
|
-
* reached on model
|
|
143
|
+
* reached on model meta/muse-spark-1.3-contributor. Try again in 20h 4m"}}.
|
|
142
144
|
*
|
|
143
145
|
* `modelId` is the name Cline spells in its own body, which is a different
|
|
144
|
-
* namespace from the id this proxy requests (measured live 2026-
|
|
145
|
-
* for `cline-free/
|
|
146
|
-
* `
|
|
146
|
+
* namespace from the id this proxy requests (measured live 2026-10-13: we ask
|
|
147
|
+
* for `cline-free/muse-spark-1.3-contributor`, Cline answers about
|
|
148
|
+
* `meta/muse-spark-1.3-contributor`). The limit cache is therefore keyed by the
|
|
147
149
|
* requested id; `modelId` is diagnostics only.
|
|
148
150
|
*/
|
|
149
151
|
export interface ClineFreeLimit {
|
package/src/config.ts
CHANGED
|
@@ -31,6 +31,17 @@ export const OPENCODE_API_URL = `${UPSTREAM_OPENCODE}/v1`;
|
|
|
31
31
|
// supplied at call time (never stored here).
|
|
32
32
|
export const CLINE_API_BASE = "https://api.cline.bot/api/v1";
|
|
33
33
|
export const CLINE_CHAT_URL = `${CLINE_API_BASE}/chat/completions`;
|
|
34
|
+
// OVHcloud AI Endpoints serves OpenAI-compatible chat completions with no
|
|
35
|
+
// credential at all (probed keyless 2026-10-13: no Authorization header,
|
|
36
|
+
// 200). Direct-only: OVH has no Zen-style per-IP gate to route around, so
|
|
37
|
+
// it never rides the relay pool and is deliberately absent from the deployed
|
|
38
|
+
// relay allowlist (src/deploy.ts), which keeps the relay surface at exactly
|
|
39
|
+
// two upstreams. Chat-only: OVH's responses endpoint rejects every array
|
|
40
|
+
// input shape with 422 "input: data did not match any variant of untagged
|
|
41
|
+
// enum ResponseInput" and accepts only a bare string (probed 2026-10-13), so
|
|
42
|
+
// a responses-path caller is translated to chat upstream and back.
|
|
43
|
+
export const OVH_API_BASE = "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1";
|
|
44
|
+
export const OVH_CHAT_URL = `${OVH_API_BASE}/chat/completions`;
|
|
34
45
|
|
|
35
46
|
// ── Network & Server defaults ───────────────────────────────────────
|
|
36
47
|
export const DEFAULT_PORT = 28180;
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* pi-freeflow — Modular, high-resiliency LLM extension for Pi & Oh My Pi (OMP)
|
|
3
3
|
*
|
|
4
|
-
* Provides access to
|
|
4
|
+
* Provides access to 36 free models (10 OpenCode Zen + 15 KiloCode Gateway + 2 Cline + 9 OVH) with:
|
|
5
5
|
* - Single-port daemon reuse on 28180 across concurrent subagents
|
|
6
6
|
* - Multi-cloud rolling egress relays (Vercel Edge, Cloudflare, Deno)
|
|
7
7
|
* - 0ms instant startup with verified static catalog and background live health checks
|
|
@@ -126,7 +126,7 @@ export function buildProviderConfig(
|
|
|
126
126
|
id: m.id,
|
|
127
127
|
name: m.name,
|
|
128
128
|
api: m.api,
|
|
129
|
-
owned_by: m.source === "kilo" ? "kilocode" : m.source === "cline" ? "clinecode" : "opencode",
|
|
129
|
+
owned_by: m.source === "kilo" ? "kilocode" : m.source === "cline" ? "clinecode" : m.source === "ovh" ? "ovhcloud" : "opencode",
|
|
130
130
|
reasoning: m.reasoning,
|
|
131
131
|
thinking: m.reasoning
|
|
132
132
|
? {
|
|
@@ -146,7 +146,7 @@ export function buildProviderConfig(
|
|
|
146
146
|
}
|
|
147
147
|
: m.api === "openai-responses"
|
|
148
148
|
? { sessionAffinityFormat: "openai-nosession" }
|
|
149
|
-
: m.source === "kilo" || m.source === "cline"
|
|
149
|
+
: m.source === "kilo" || m.source === "cline" || m.source === "ovh"
|
|
150
150
|
? {
|
|
151
151
|
supportsDeveloperRole: false,
|
|
152
152
|
supportsReasoningEffort: !!m.thinkingLevelMap,
|