pi-freeflow 1.3.3 → 1.3.7

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/README.md CHANGED
@@ -1,135 +1,134 @@
1
1
  # pi-freeflow 🌊
2
2
 
3
- > **23 free models. Up to 1M context (66K–1M per model). Zero API keys. Infinite scale via your own cloud relay.**
3
+ > **23 free models. Up to 1M context. Zero API keys. Infinite scale via your own relay pool.**
4
4
 
5
- **Thin by design:** `model list + dumb relay + log` host `pi-ai` owns thinking, normalization & provider magic. We just make it _free, fast, and unbreakable_.
5
+ Thin by design: model list + dumb relay + log. Host `pi-ai` owns thinking, normalization & provider magic. We just make it free, fast, and unbreakable.
6
6
 
7
- [![npm version](https://img.shields.io/npm/v/pi-freeflow?color=00d4ff)](https://www.npmjs.com/package/pi-freeflow)
8
- [![npm downloads](https://img.shields.io/npm/dm/pi-freeflow)](https://www.npmjs.com/package/pi-freeflow)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-00ff88.svg)](LICENSE)
10
- [![Pi & OMP](https://img.shields.io/badge/Works%20with-Pi%20%26%20Oh%20My%20Pi-7c3aed)](https://omp.sh)
7
+ [![npm version](https://img.shields.io/npm/v/pi-freeflow?style=flat-square&color=00E5FF)](https://www.npmjs.com/package/pi-freeflow)
8
+ [![npm downloads](https://img.shields.io/npm/dm/pi-freeflow?style=flat-square)](https://www.npmjs.com/package/pi-freeflow)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
+ [![Pi](https://img.shields.io/badge/Powered%20by-Pi-7c3aed?style=flat-square)](https://github.com/badlogic/pi-ai)
11
+ [![Oh My Pi](https://img.shields.io/badge/Compatible-OMP-black?style=flat-square)](https://github.com/coder/oh-my-pi)
11
12
 
12
- > **Join devs bypassing rate limits with their own relay pools — BYO, add as many as you need.**
13
+ **Join devs bypassing rate limits with their own relay pools — BYO, add as many as you need.**
13
14
 
14
- ## Why you’re here
15
+ ---
16
+
17
+ ### Why FreeFlow?
15
18
 
16
19
  You love Pi. You love free models. You hate:
17
20
 
18
- - `429 Rate Limit` killing your 10-parallel subagent fleet
19
- - `Paid model leaked` into your picker
20
- - `Thinking` silently disabled because `reasoning_effort: max` was rejected
21
- - Paying for `1M context` you should get for free
21
+ - **429 Rate Limit** killing your 10-parallel subagent fleet
22
+ - Paid models leaking into your picker
23
+ - `reasoning_effort: max` rejected and thinking silently disabled
24
+ - Paying for 1M context you should get for free
22
25
 
23
26
  **FreeFlow fixes all three — in 17 files, 102KB.**
24
27
 
25
- ---
26
-
27
- ## What you get (and what you don’t pay for)
28
+ ### Features
28
29
 
29
- | You get | Value | Cost |
30
- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |
31
- | **23 curated free models** — 9 OpenCode Zen + 14 Kilo, Up to 1M (66K1M per model), vision-ready | $0 | $0 |
32
- | **BYO relay pool** — Cloudflare Workers + Vercel Edge, round-robin, seamless `429→next` (default ships direct, add via `/freeflow use <url>` / `deploy`) | $0 (your free tiers) | $0 |
33
- | **Dumb proxy that never breaks** — `127.0.0.1:18080`, host-normalized, pathname-guarded `/v1/models` | $0 | $0 |
34
- | **Real logs** — `~/.pi/agent/pi-freeflow.log` 5MB rotate, debug toggle | $0 | $0 |
30
+ | What You Get | Value | Cost |
31
+ | :--- | :--- | :--- |
32
+ | **23 Curated Free Models** — 9 OpenCode Zen + 14 Kilo, 66K-1M context, vision-ready | Unlimited | **$0** |
33
+ | **BYO Relay Pool** — Cloudflare Workers + Vercel Edge, round-robin, seamless `429 next` | Auto-scale | **$0** (your free tiers) |
34
+ | **Dumb Proxy That Never Breaks** — `127.0.0.1:18080`, host-normalized, pathname-guarded `/v1/models` | 100% uptime | **$0** |
35
+ | **Real Logs** — `~/.pi/agent/pi-freeflow.log`, 5MB rotate, debug toggle | Observable | **$0** |
35
36
 
36
- > **Thin by design:** `model list + relay proxy + log` host `pi-ai` owns thinking & normalization.
37
+ Philosophy: **Thin by design.** We only ship model list + relay proxy + log. Host owns thinking & normalization.
37
38
 
38
39
  ---
39
40
 
40
- ## 23 Models — One Command
41
+ ### 23 Models — One Command
41
42
 
42
43
  ```bash
43
44
  /model → freeflow → pick
44
45
  ```
45
46
 
46
- ### OpenCode Zen (9) — Responses & Chat
47
+ #### OpenCode Zen (9) — Responses & Chat API
48
+ Best for long-context reasoning. All vision-ready models marked.
47
49
 
48
- | Model | Context | Max | Thinking | Vision |
49
- | --------------------------------- | -------- | ---- | ----------------- | ------ |
50
- | `muse-spark-1.2-contributor-free` | **1M** | 131K | `minimal→max` | ✅ |
51
- | `deepseek-v4-flash-free` | **1M** | 384K | `minimal→max` | ❌ |
52
- | `x-preview-f-free` | **1M** | 131K | `low/high/max` | ✅ |
53
- | `mimo-v2.5-free` | **1M** | 131K | `low/medium/high` | ✅ |
54
- | `laguna-s-2.1-free` | **1M** | 131K | `minimal→max` | ❌ |
55
- | `nemotron-3.5-lightning-free` | **1M** | 262K | `minimal→max` | ❌ |
56
- | `nemotron-3-ultra-free` | **1M** | 128K | `minimal→max` | ❌ |
57
- | `hy3-free` | **262K** | 128K | `minimal→max` | ❌ |
58
- | `big-pickle` | **200K** | 32K | `high/max` | ❌ |
50
+ | Model | Context | Max Output | Thinking | Vision |
51
+ | :--- | :--- | :--- | :--- | :--- |
52
+ | `claude-sonnet-4.5-free` / `muse-spark-1.2-contributor-free` | 1M | 131K | `minimal max` | ✅ |
53
+ | `deepseek-v4-flash-free` | 1M | 384K | `minimal max` | ❌ |
54
+ | `grok-code-fast-1-preview-f-free` / `x-preview-f-free` | 1M | 131K | `low / high / max` | ✅ |
55
+ | `mimo-v2.5-free` | 1M | 131K | `low / medium / high` | ✅ |
56
+ | `minimax-m2.1-free` / `laguna-s-2.1-free` | 1M | 131K | `minimal max` | ❌ |
57
+ | `nemotron-3.5-lightning-free` | 1M | 262K | `minimal max` | ❌ |
58
+ | `nemotron-3-ultra-free` | 1M | 128K | `minimal max` | ❌ |
59
+ | `qwen3-coder-480b-free` / `hy3-free` | 262K | 128K | `minimal max` | ❌ |
60
+ | `big-pickle` | 200K | 32K | `high / max` | ❌ |
59
61
 
60
- ### Kilo Gateway (14) — OpenRouter
62
+ #### Kilo Gateway (14) — OpenRouter Compatible
63
+ Zero-config, `Bearer kilo-free`.
61
64
 
62
- `dots-3-note-preview:free` **512K**, `step-3.7-flash:free` 262K, `nemotron-3-nano-omni:free` 256K, `nemotron-3-ultra-550b:free` **1M**, `nemotron-3-super:free` 262K, `hy3:free` 262K, `north-mini-code:free` 256K, `laguna-s/xs:free` 262K, `lfm-2.5:free` 66K, `kilo-auto/free`, `openrouter/free`, `content-safety:free` + 2 more.
65
+ `dots-3-note-preview:free` (512K), `step-3.7-flash:free` (262K), `nemotron-3-nano-omni:free` (256K), `nemotron-3-ultra-550b:free` (1M), `nemotron-3-super:free` (262K), `hy3:free` (262K), `north-mini-code:free` (256K), `minimax-m2.1/xs:free` (262K), `lfm-2.5:free` (66K), `kilo-auto/free`, `openrouter/free`, `content-safety:free` + 2 more.
63
66
 
64
- All `off→null` (hidden) host decides budgets, not us.
67
+ > All `off null` (hidden). Host decides token budgets, not us.
65
68
 
66
- ---
67
-
68
- ## The magic: BYO relays, 0 rate limits
69
+ ### How It Works — The Magic: BYO Relays, Zero Rate Limits
69
70
 
70
- ```text
71
- You → 127.0.0.1:18080 (dumb) → x-relay-target → N egress IPs (your pool) → opencode.ai / api.kilo.ai
72
- ↑ host already normalized thinking → proxy just forwards
73
71
  ```
74
-
75
- - **Round-robin per request** 10 parallel subagents hit N different primaries (your pool size), no thundering herd
76
- - **Seamless 429** — `429/502/503/504` → instant roll to next, never `429` to agent
77
- - **Exhausted? Direct fallback** — if all relays are 429 (global limit), transparent `direct fetch` — host shows `rate limit` only when truly global
78
- - **No live catalog fetch** — `24h DISK_CACHE_ONLY`, never `fetch` from subagent → no `Unable to connect`
79
-
80
- **Real log (1.3.1 thin):**
81
-
82
- ```text
83
- candidates:N → relay-A 429 rolling → relay-B 200 in 1.2s → 98 chunks 663KB done
72
+ You → 127.0.0.1:18080 (dumb proxy, host-normalized) → x-relay-target → N egress IPs (your pool) → opencode.ai / api.kilo.ai
73
+ host already normalized thinking proxy just forwards
84
74
  ```
85
75
 
76
+ - **Round-robin per request** — 10 parallel subagents hit N different egress IPs (your pool size). No thundering herd.
77
+ - **Seamless 429 roll** — `429 / 502 / 503 / 504` → instant roll to next relay, never 429 to agent.
78
+ - **Exhausted? Direct fallback** — If all relays are 429 (global limit), transparent direct fetch. Host shows rate limit only when truly global.
79
+ - **No live catalog fetch** — 24h `DISK_CACHE_ONLY`, never fetch from subagent → no `Unable to connect`.
80
+ - **Real log (v1.3.1 thin):** `candidates:N → relay-A 429 rolling → relay-B 200 in 1.2s → 98 chunks 663KB done`
81
+
86
82
  You bring the relays (free tiers). We bring the rolling.
87
83
 
88
84
  ---
89
85
 
90
- ## 30-second Setup
91
-
92
- ### 1. Install (pick your host)
86
+ ### Quick Start — 30 Seconds
93
87
 
94
- **Oh My Pi (recommended):**
88
+ #### 1. Install
95
89
 
90
+ **Oh My Pi (Recommended):**
96
91
  ```bash
97
92
  omp plugin install pi-freeflow
98
93
  # or local dev
99
94
  omp plugin link /path/to/pi-freeflow
100
- ````
95
+ ```
101
96
 
102
97
  **Pi:**
103
-
104
98
  ```bash
105
99
  pi install npm:pi-freeflow
106
100
  ```
107
101
 
108
- ### 2. Pick a model
102
+ #### 2. Pick a Model
109
103
 
110
104
  ```bash
111
105
  omp
112
- /model → freeflow → muse-spark-1.2 (1M) → max
106
+ /model → freeflow → claude-sonnet-4.5 (1M) → max
107
+
113
108
  # or CLI
114
- omp -p --model freeflow/muse-spark-1.2-contributor-free "build me a SaaS"
109
+ omp -p --model freeflow/claude-sonnet-4.5-contributor-free "build me a SaaS"
115
110
  ```
116
111
 
117
- ### 3. (Optional but 🔥) Add your free relays — BYO, scale as you add
112
+ #### 3. (Optional but 🔥) Add Your Free Relays
118
113
 
119
- **One Cloudflare Worker (100k req/day, no 25s timeout):**
114
+ Scale infinitely. Default ships direct, add relays via `/freeflow use <url>`.
120
115
 
121
- 1. `dash.cloudflare.com Workers → Create → Deploy → Edit code` → paste the Worker relay snippet below Deploy
122
- 2. `omp` → `/freeflow use https://your.workers.dev`
116
+ **Option A: One Cloudflare Worker (100k req/day, no 25s timeout)**
117
+ 1. Go to `dash.cloudflare.com` → Workers Create → Deploy → Edit code
118
+ 2. Paste the Worker relay snippet from `/reference/worker-relay.js`
119
+ 3. Deploy and add it:
123
120
 
124
- **Six Vercel Edges (1M req/mo):**
121
+ ```bash
122
+ omp → /freeflow use https://your.workers.dev
123
+ ```
125
124
 
125
+ **Option B: Six Vercel Edges (1M req/mo) — Auto Deploy**
126
126
  ```bash
127
127
  /freeflow deploy # prompts token in-memory, auto-adds to pool
128
128
  # or manual: vercel.json → api/relay.js
129
129
  ```
130
130
 
131
- **Check pooling:**
132
-
131
+ **Verify your pool:**
133
132
  ```bash
134
133
  /freeflow status # relay-A 1/N (ON) → candidates:N
135
134
  /freeflow logs # tail -25
@@ -138,45 +137,63 @@ cat ~/.pi/agent/pi-freeflow.log | tail -n 20
138
137
 
139
138
  Done. Subagents now follow parent proxy — `Unable to connect` is history.
140
139
 
141
- ---
140
+ ### Logs & Debugging
142
141
 
143
- ## Thin vs Fat
142
+ ```bash
143
+ /freeflow logs
144
+ cat ~/.pi/agent/pi-freeflow.log | tail -n 50
144
145
 
145
- | Fat plugin (before) | Thin FreeFlow (now) |
146
- | ------------------------------------------- | --------------------------------------------------- |
147
- | `src/normalizer.ts` 200 LOC duplicates host | **Deleted** — host `pi-ai` owns 11 `thinkingFormat` |
148
- | Live `fetch` 10s in subagent → timeout | **Disk-only 24h**, proxy-only |
149
- | `400` loops N× relays | **Narrow 429/5xx only**, `400` surfaces instantly |
150
- | `GET /v1/models?foo` leaks paid | **Pathname-guarded** |
146
+ # debug toggle
147
+ /freeflow debug on
148
+ ```
151
149
 
152
- Result: **<500 LOC core, 29 tests PASS, typecheck PASS**.
150
+ Log rotation at 5MB. Clean, parseable, real-time.
153
151
 
154
- ---
152
+ ### Philosophy: Thin vs Fat
155
153
 
156
- ## FAQ
154
+ | Fat Plugin (Before) | Thin FreeFlow (Now) |
155
+ | :--- | :--- |
156
+ | `src/normalizer.ts` 200 LOC duplicates host | Deleted — host `pi-ai` owns 11 `thinkingFormat` |
157
+ | Live fetch 10s in subagent → timeout | Disk-only 24h, proxy-only |
158
+ | 400 loops N× relays | Narrow 429/5xx only, 400 surfaces instantly |
159
+ | `GET /v1/models?foo` leaks paid | Pathname-guarded |
157
160
 
158
- **Do I need API keys?** No. `Kilo` uses `Bearer kilo-free`, `OpenCode` uses `opencodeHeaders()`.
161
+ **Result: <500 LOC core, 29 tests PASS, typecheck PASS.**
159
162
 
160
- **What if all relays 429?** Proxy tries direct. If that’s also 429, Pi shows `rate limit` — that means global upstream limit, even without relay you’d be 429.
163
+ ### FAQ
161
164
 
162
- **Can I use without relays?** Yes. `/freeflow off` → direct. Add relays later to scale.
165
+ **Do I need API keys?**
166
+ No. Kilo uses `Bearer kilo-free`, OpenCode uses `opencodeHeaders()`.
163
167
 
164
- **Where’s `normalizer`?** Deleted in `1.3.0`. If `zai/qwen/deepseek` thinking broke before, it’s fixed now because host handles it.
168
+ **What if all relays are 429?**
169
+ Proxy tries direct. If that's also 429, Pi shows rate limit — that means global upstream limit, even without relay you'd be 429.
165
170
 
166
- ---
171
+ **Can I use without relays?**
172
+ Yes. `/freeflow off` → direct. Add relays later to scale.
173
+
174
+ **Where's the normalizer?**
175
+ Deleted in 1.3.0. If zai/qwen/deepseek thinking broke before, it's fixed now because host handles it.
167
176
 
168
- ## Sell yourself, not the plugin
177
+ **Why is context free?**
178
+ We use OpenCode Zen & Kilo free tiers. You pay only with your own Cloudflare/Vercel free tiers for egress.
169
179
 
170
- > “I shipped 10 parallel subagents on 1M context, zero keys, zero 429s. FreeFlow did the rolling, Pi did the thinking.”
180
+ ### Contributing
171
181
 
172
- **Start now:**
182
+ > "I shipped 10 parallel subagents on 1M context, zero keys, zero 429s. FreeFlow did the rolling, Pi did the thinking."
173
183
 
174
184
  ```bash
175
- omp plugin install pi-freeflow && omp --model freeflow/muse-spark-1.2-contributor-free --thinking max "make it sell"
185
+ git clone https://github.com/trefeon/pi-freeflow
186
+ pnpm install
187
+ pnpm test
176
188
  ```
177
189
 
178
- ---
190
+ PRs welcome. `reference/` holds pi, oh-my-pi, opencode, kilocode shallow clones for audit (gitignored).
179
191
 
180
- ## License
192
+ ### License
181
193
 
182
- MIT © trefeon — PRs welcome. `reference/` holds `pi`, `oh-my-pi`, `opencode`, `kilocode` shallow clones for audit (gitignored).
194
+ MIT © trefeon
195
+
196
+ Start now:
197
+ ```bash
198
+ omp plugin install pi-freeflow && omp --model freeflow/claude-sonnet-4.5-contributor-free --thinking max "make it sell"
199
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-freeflow",
3
3
  "type": "module",
4
- "version": "1.3.3",
4
+ "version": "1.3.7",
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",
@@ -20,7 +20,7 @@
20
20
  "license": "MIT",
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "https://github.com/trefeon/pi-freeflow.git"
23
+ "url": "git+https://github.com/trefeon/pi-freeflow.git"
24
24
  },
25
25
  "homepage": "https://github.com/trefeon/pi-freeflow#readme",
26
26
  "omp": {
package/src/catalog.ts CHANGED
@@ -16,10 +16,13 @@ import {
16
16
  } from "./config.ts";
17
17
  import { log, logDebug, logWarn } from "./logger.ts";
18
18
  import {
19
+ ALL_MODELS,
19
20
  KILO_MODELS,
21
+ KILO_MODEL_IDS,
20
22
  KNOWN_MODELS,
21
23
  MODEL_MAP,
22
24
  OPENCODE_MODELS,
25
+ getAllRegisteredModels,
23
26
  } from "./models.ts";
24
27
  import type {
25
28
  CatalogCacheData,
@@ -32,10 +35,10 @@ import type {
32
35
  * In-memory cache of currently active/available free models.
33
36
  * Initialized with all 23 verified models for 0ms instant availability.
34
37
  */
35
- let aliveCatalog: RegisteredModel[] = [
36
- ...OPENCODE_MODELS.map((m) => ({ ...m, source: "opencode" as const })),
37
- ...KILO_MODELS.map((m) => ({ ...m, source: "kilo" as const })),
38
- ];
38
+ let aliveCatalog: RegisteredModel[] = ALL_MODELS.map((m) => ({
39
+ ...m,
40
+ source: KILO_MODEL_IDS.has(m.id) ? ("kilo" as const) : ("opencode" as const),
41
+ }));
39
42
  /**
40
43
  * Get current in-memory alive catalog
41
44
  */
@@ -194,7 +197,7 @@ export async function refreshCatalog(force = false): Promise<RegisteredModel[]>
194
197
  return aliveCatalog;
195
198
  }
196
199
  // Stale cache still better than empty — return it without network
197
- if (disk.models.length === 23) {
200
+ if (disk.models.length >= 23) {
198
201
  aliveCatalog = disk.models;
199
202
  return aliveCatalog;
200
203
  }