pi-freeflow 1.11.1 → 1.12.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 +221 -209
- package/README.md +8 -6
- package/package.json +61 -61
- package/src/catalog.ts +3 -2
- package/src/index.ts +1 -1
- package/src/models.ts +30 -10
- package/src/relay.ts +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,209 +1,221 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 1.
|
|
4
|
-
|
|
5
|
-
###
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- **
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
###
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
- **
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- **
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
- **
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
-
|
|
116
|
-
|
|
117
|
-
## 1.9.
|
|
118
|
-
|
|
119
|
-
### Fixes
|
|
120
|
-
|
|
121
|
-
- **
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
|
|
158
|
-
## 1.
|
|
159
|
-
|
|
160
|
-
###
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
|
|
180
|
-
## 1.
|
|
181
|
-
|
|
182
|
-
-
|
|
183
|
-
|
|
184
|
-
## 1.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Free-model picker grows from 24 to 26: adds Nex N2.5 Pro, Nex N2.5 Mini, and Ling 3.0 Flash VL, and removes the discontinued Inkling entry. A new Stealth Models Watchlist docs page tracks masked preview IDs users ask about.
|
|
8
|
+
|
|
9
|
+
## 1.11.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 549b66e: Oversized requests no longer fail at the relay hop: when a relay answers 413 payload limit, the proxy transparently tries the next relay and then the direct route, keeping the stream alive. Long sessions that outgrow the relay payload cap now complete instead of surfacing a function payload error.
|
|
14
|
+
|
|
15
|
+
## 1.11.1
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Apologies for the daemon disconnect bug introduced in v1.11.0: in multi-agent workflows or when subagents, evaluations, and background tasks completed, the extension prematurely detached from the local proxy daemon, causing the proxy to shut down while your main session remained active. The heartbeat connection now persists throughout your active terminal session.
|
|
20
|
+
- Increased local health check and liveness probe timeouts from 800ms and 500ms to 2500ms and 1500ms, with an automatic probe retry to avoid false-alarm daemon restarts during heavy concurrent streaming.
|
|
21
|
+
- Added unhandled error logging inside the daemon to prevent silent process exits.
|
|
22
|
+
- Fresh installs now log full HTTP lifecycle debug output by default so diagnostic reports contain complete request context; turn it off anytime with `/freeflow debug off`.
|
|
23
|
+
|
|
24
|
+
## 1.11.0
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- Proxy daemon now stays up while any session uses it, even when idle. It shuts down only after the last session leaves, instead of retiring after a short quiet window.
|
|
29
|
+
|
|
30
|
+
## 1.10.0
|
|
31
|
+
|
|
32
|
+
### Minor Changes
|
|
33
|
+
|
|
34
|
+
- cf48598: Hands-free proxy recovery plus catalog refresh: the proxy now watches its own health, restarts with backoff instead of leaving a dead port, and can start on login. Removed two discontinued free models from the picker.
|
|
35
|
+
|
|
36
|
+
All notable changes to pi-freeflow. Public, user-visible behavior only.
|
|
37
|
+
|
|
38
|
+
## 1.9.9 - 2026-09-06
|
|
39
|
+
|
|
40
|
+
### Fixes
|
|
41
|
+
|
|
42
|
+
- **Removed our own request cap — sorry, that one was on us.** The proxy used to enforce a built-in request limit and could answer 429 before upstream quota was actually exhausted. That was a bug, not your quota. From this version the proxy never rejects on quota itself: a 429 only surfaces when the upstream — and every relay in your pool — genuinely is rate-limited, and that response now points you at `/freeflow deploy` to add relay egress.
|
|
43
|
+
|
|
44
|
+
## 1.9.8 - 2026-09-06
|
|
45
|
+
|
|
46
|
+
### Fixes
|
|
47
|
+
|
|
48
|
+
- **Stale model list heals itself (follow-up to #6).** If your saved model list predates a newly added model, the background refresh now repairs the entry (correct endpoint and details) instead of sending requests to the wrong address — no manual `/freeflow refresh` or cache deletion needed.
|
|
49
|
+
- **Paid models stay out of the picker even from old saved lists.** Every read of the saved model list now drops non-free entries, so models requiring an API key cannot linger after an upgrade.
|
|
50
|
+
- **Old saved lists without a sync marker now re-sync once.** A saved list that could never trigger a network check now performs one plain revalidation (then syncs normally), so newly added free models appear without manual intervention. Missing or corrupt lists still fall back silently with no network call.
|
|
51
|
+
- **Upstream errors are now visible in the proxy log.** Failed upstream responses log their status code and model, and a model routed to the wrong endpoint logs the mismatch with the fix (restart Pi/OMP after upgrade).
|
|
52
|
+
|
|
53
|
+
### Validation
|
|
54
|
+
|
|
55
|
+
- TypeScript typecheck passed cleanly (`tsc --noEmit`).
|
|
56
|
+
- Full test suite passed on Windows (304 tests) and Ubuntu Linux (`acerblue`, 305/305 tests passed), including new regressions for the stale-cache shape from #6.
|
|
57
|
+
- Live sweep of all 26 models through a fresh install on `acerblue`: 23/26 answered on first try (both Muse Spark models via the Responses endpoint); the 3 misses are upstream per-model daily quotas (429), zero server errors.
|
|
58
|
+
|
|
59
|
+
## 1.9.7 - 2026-09-06
|
|
60
|
+
|
|
61
|
+
### Fixes
|
|
62
|
+
|
|
63
|
+
- **Model picker only shows verified free models (fixes #6).** Background catalog refresh now filters out non-free models from upstream endpoints so paid models requiring an API key no longer leak into your picker.
|
|
64
|
+
- **Relay pool automatically recovers from dead deployments (fixes #5).** If a relay URL in your pool returns an infrastructure 404 (such as a missing or deleted Vercel deployment), the proxy marks it as failed and immediately rolls over to your next healthy relay or direct mode instead of getting trapped in a 404 loop.
|
|
65
|
+
|
|
66
|
+
### Changes
|
|
67
|
+
|
|
68
|
+
- **Updated model catalog (26 verified free models: 7 OpenCode Zen + 19 KiloCode Gateway).**
|
|
69
|
+
- Added `inclusionai/ling-3.0-flash-sante:free` (Ling 3.0 Flash Sante, 262K context, 32K output, reasoning supported). Clean CLI alias `ling-3.0-flash-sante` supported.
|
|
70
|
+
- Removed `laguna-s-2.1-free` (OpenCode Zen) after upstream dropped free-tier access. `poolside/laguna-s-2.1:free` on Kilo remains active.
|
|
71
|
+
- **Public by default for new relay deployments.** Relays deployed via `/freeflow deploy` are now public by default with no mandatory authentication tokens. This enables seamless copy-paste migration across proxy tools (such as 9router) while maintaining safety guards for allowed AI upstreams.
|
|
72
|
+
|
|
73
|
+
### Validation
|
|
74
|
+
|
|
75
|
+
- TypeScript typecheck passed cleanly (`tsc --noEmit`).
|
|
76
|
+
- Full test suite passed across Windows (299 tests) and Ubuntu Linux (`acerblue-local`, 300/300 tests passed).
|
|
77
|
+
- End-to-end concurrency and failover stress testing verified (100 parallel requests, 20 subagent leases, burst failover).
|
|
78
|
+
|
|
79
|
+
## 1.9.6 - 2026-09-03
|
|
80
|
+
|
|
81
|
+
### Fixes
|
|
82
|
+
|
|
83
|
+
- **Hiding the status widget now sticks.** `/freeflow hide` survives restarts, new sessions, and background update notices — previously the widget could reappear on the next session.
|
|
84
|
+
- **Calmer startup with many sessions.** Sessions starting at the same time now converge on a single background proxy instead of each spawning its own; a spawn that never becomes ready falls back to in-process mode instead of running untracked.
|
|
85
|
+
- **Survives daemon restarts mid-session.** If the background proxy is replaced while sessions run, connected sessions re-register automatically instead of silently losing their lease (which could retire the daemon mid-use).
|
|
86
|
+
- **Stale-version cleanup targets the right process.** Windows port matching is now exact, and Linux without `lsof`/`fuser` resolves the holder via `/proc` instead of giving up.
|
|
87
|
+
- **`/freeflow logs --follow` no longer runs forever.** The live tail stops when the session ends and caps burst output; the update/install subprocess now has a 2-minute timeout.
|
|
88
|
+
|
|
89
|
+
### Validation
|
|
90
|
+
|
|
91
|
+
- `npx tsc --noEmit` clean, `npm test` 299 (298 pass + 1 Linux-only skip) + smoke green on Windows; stress harness 7/7 on Windows and Linux `acerblue-local`. **`macOS not tested`** this cycle.
|
|
92
|
+
|
|
93
|
+
## 1.9.5 - 2026-09-03
|
|
94
|
+
|
|
95
|
+
### Changes
|
|
96
|
+
|
|
97
|
+
- **Catalog refreshed against live upstream model lists (26 models: 8 OpenCode Zen + 18 KiloCode Gateway).** Re-checked both upstreams against their live endpoints and live inference probes:
|
|
98
|
+
- **Added** `muse-spark-1.3-contributor-free` (OpenCode Zen, Responses API, 1M context, 131K output, vision) — verified live: completes with reasoning, accepts effort levels, and answers vision queries.
|
|
99
|
+
- **Removed** `hy3-free` (OpenCode Zen) — upstream no longer serves it (`Model hy3-free is not supported`).
|
|
100
|
+
- **Removed** `tencent/hy3:free` and `meituan/longcat-2.0-free` (KiloCode Gateway) — upstream free tier dropped them (model unavailable / sign-in required).
|
|
101
|
+
- Pruned IDs added to the dead-model filter so a stale disk cache cannot resurrect them.
|
|
102
|
+
|
|
103
|
+
### Validation
|
|
104
|
+
|
|
105
|
+
- `npx tsc --noEmit` clean, `npm test` full suite green on Windows.
|
|
106
|
+
|
|
107
|
+
## 1.9.4 - 2026-09-02
|
|
108
|
+
|
|
109
|
+
### Dependencies
|
|
110
|
+
|
|
111
|
+
- **Zero runtime dependencies.** Removed `undici@8.10.0` — `pi` (`0.84.4`) and `omp` (`18.1.3`) already bundle `undici` 6.x/7.x and expose `global fetch` with keep-alive pooling. `relayFetch` and proxy now use `global fetch` directly (`src/relay.ts` `Agent` + `canUseCustomDispatcher` + `dispatcher: agent` removed; `src/proxy.ts` dispatcher removed). Keeps thin `11.3k` + `298 tests` + `0 deps` compatible directly with `reference/pi` + `reference/oh-my-pi`.
|
|
112
|
+
|
|
113
|
+
### Validation
|
|
114
|
+
|
|
115
|
+
- `npx tsc --noEmit` clean, `npm test 298/298` on **Windows** (`omp/18.1.3`, `pi 0.84.4`) and **Linux `acerblue-local`** (`Ubuntu 6.8.0-138`, `node v22.23.2`, `pi 0.84.4`) via `/tmp/pi-freeflow-validation`. **`macOS not tested`** this cycle.
|
|
116
|
+
|
|
117
|
+
## 1.9.3 - 2026-09-02
|
|
118
|
+
|
|
119
|
+
### Fixes
|
|
120
|
+
|
|
121
|
+
- **Windows console flood fixed.** Two Windows-only helpers flashed a visible `conhost`/`cmd` window on every daemon probe: `netstat -ano | findstr :28180` / `taskkill` in the stale-daemon replace path and `spawn(omp|npm, shell:true)` for `/freeflow update`. Both now use `windowsHide: true` (no-op on Linux/macOS) and `spawnWithProgress` was refactored to `Promise.withResolvers` to satisfy `ts-promise-with-resolvers`. Idle `pi` no longer spawns many visible consoles even after closing the terminal (detached daemon at `127.0.0.1:28180` survives by design; `beatOnce` 10s heartbeat now throttled 2s via `lastSpawnAt`).
|
|
122
|
+
- Daemon spawn now throttled per-process (2s) as a storm guard when `28180` is contended or blocked; the `ensuring` guard + `waitForReady 5s` already prevented tight loops.
|
|
123
|
+
|
|
124
|
+
### Validation
|
|
125
|
+
|
|
126
|
+
- `npx tsc --noEmit` clean, `npm test 279/279` on **Windows** (`omp/18.1.3`, `pi 0.84.4`) and **Linux `acerblue-local`** (`Ubuntu 6.8.0-138`, `node v22.23.2`, `pi 0.84.4`) via `/tmp/pi-freeflow-validation`. **`macOS not tested`** this cycle.
|
|
127
|
+
- Reporter `LOYINuts` issue #3 (`pi idle creates many sessions → force reboot`) — `grep -r rtk src` ∅ confirms `rtk` is an external global skill (`~/.agents/skills/rtk` → `Command::new("cmd")` without `CREATE_NO_WINDOW`), not `pi-freeflow`. After this fix, closing the terminal no longer leaves flashing zombies; kill via `netstat -ano | findstr :28180` → `taskkill /F /PID` or `/freeflow kill`.
|
|
128
|
+
|
|
129
|
+
## 1.9.2 - 2026-08-31
|
|
130
|
+
|
|
131
|
+
### Fixes
|
|
132
|
+
|
|
133
|
+
- **Closing one session no longer stops the shared local proxy.** The proxy daemon
|
|
134
|
+
is now a fully detached background process: it outlives any single OMP/Pi session
|
|
135
|
+
(previously, closing the session that owned the daemon could shut it down even
|
|
136
|
+
while other sessions were still using it). It retires by itself only when no
|
|
137
|
+
session is connected, no request is in flight, and it has been idle for a grace
|
|
138
|
+
period. The next use starts it again automatically.
|
|
139
|
+
- New command: `/freeflow kill` (aliases `stop`, `shutdown`) stops the background
|
|
140
|
+
daemon on demand. The next freeflow use restarts it.
|
|
141
|
+
|
|
142
|
+
### Improvements
|
|
143
|
+
|
|
144
|
+
- The proxy tracks connected sessions and last request time; `/freeflow status`
|
|
145
|
+
and the health endpoint now report active session leases, so you can see when
|
|
146
|
+
other sessions are keeping the daemon alive.
|
|
147
|
+
- Docs: the command reference now lists `kill`, and the FAQ explains the shared
|
|
148
|
+
daemon lifecycle (survives session close; self-retires when unused).
|
|
149
|
+
|
|
150
|
+
## 1.9.1 - 2026-08-30
|
|
151
|
+
|
|
152
|
+
### Fixes
|
|
153
|
+
|
|
154
|
+
- Stale-daemon guard completed: a pre-1.9.0 daemon cannot report its in-flight requests, and usage cannot be verified — so it is now left running instead of being replaced. Previously such a daemon could still be killed mid-stream while busy (a one-time window when upgrading from 1.8.x). The guarantee now holds in every case: only older, verified-idle daemons are replaced.
|
|
155
|
+
- The stale-daemon kill ritual was consolidated into one path (it was duplicated at five call sites); behavior unchanged.
|
|
156
|
+
- Tests: new coverage for the pre-1.9 daemon case; shared sandbox helpers extracted.
|
|
157
|
+
|
|
158
|
+
## 1.9.0 - 2026-08-30
|
|
159
|
+
|
|
160
|
+
### Development hardening
|
|
161
|
+
|
|
162
|
+
- Test suite now runs fully sandboxed: every test uses a temporary data directory, so no test can ever write to your real `~/.pi/agent/` files or interfere with a running local proxy. A single env override (`PI_*_DATA_DIR`) re-roots all data files for tests/CI.
|
|
163
|
+
- Added a complete mocked user-flow e2e suite: fresh install → onboarding → proxy health → direct chat → relay add/roll/fallback → guided deploy → update check → command surface — all deterministic, zero network.
|
|
164
|
+
- Docs: test counts no longer hardcoded in README (they drifted with releases); release history tracked here.
|
|
165
|
+
|
|
166
|
+
### Fixes
|
|
167
|
+
|
|
168
|
+
- **Stale-daemon replacement no longer interrupts running sessions.** The shared local proxy can be held by another OMP/Pi session; the old upgrade logic killed that holder on version mismatch, which could terminate the session that owned the proxy mid-stream. Replacement now only happens when the running daemon is strictly older AND idle (0 in-flight requests, reported via `/_health`); newer or busy daemons are reused with a log note instead. Optional opt-out: set the no-kill env to `1` (see README FAQ for upgrades).
|
|
169
|
+
|
|
170
|
+
## 1.8.2 - 2026-08-30
|
|
171
|
+
|
|
172
|
+
### Fixes & polish
|
|
173
|
+
|
|
174
|
+
- Deploy: compare-and-swap on concurrent deployments (no duplicate relays when two sessions deploy at once).
|
|
175
|
+
- Proxy: URL-encoding edge cases (`%` in paths), startup timeout and kill handling, port conflict fallback.
|
|
176
|
+
- Logs: sanitized sensitive headers in debug output.
|
|
177
|
+
- Kilo gateway models: compatibility pass for all 25 models.
|
|
178
|
+
- Docs site build included; README per-host usage guide (Oh My Pi & Pi install + pick + manage).
|
|
179
|
+
|
|
180
|
+
## 1.8.1 - 2026-08-29
|
|
181
|
+
|
|
182
|
+
- Fix: stale-daemon auto-heal is now shipped in the published package (previously only in the repo).
|
|
183
|
+
|
|
184
|
+
## 1.8.0 - 2026-08-29
|
|
185
|
+
|
|
186
|
+
### Automatic upgrades
|
|
187
|
+
|
|
188
|
+
- On version upgrade, the extension detects a stale local proxy daemon and replaces it automatically — users get fixes without manual restarts or killing sessions.
|
|
189
|
+
- Fix: client auth key stripped before reaching the opencode.ai/zen upstream (failed with 401 for some clients).
|
|
190
|
+
- 3 new free models (28 total).
|
|
191
|
+
|
|
192
|
+
## 1.7.1 - 2026-08-29
|
|
193
|
+
|
|
194
|
+
- Docs: clarified npm is the distribution channel (the package is an extension loaded by OMP/Pi, not a standalone CLI).
|
|
195
|
+
|
|
196
|
+
## 1.7.0 - 2026-08-29
|
|
197
|
+
|
|
198
|
+
- 4 new free models (25 total) with live-verified specs (context/output limits, vision, thinking levels).
|
|
199
|
+
- New alias map aligned with host model selectors.
|
|
200
|
+
|
|
201
|
+
## 1.6.1 - 2026-08-29
|
|
202
|
+
|
|
203
|
+
- Catalog: thinking-level map locked per model; docs sync.
|
|
204
|
+
|
|
205
|
+
## 1.6.0 - 2026-08-29
|
|
206
|
+
|
|
207
|
+
### Onboarding & UX
|
|
208
|
+
|
|
209
|
+
- First-run onboarding message; 429 guidance hint (add your own relay egress).
|
|
210
|
+
- `/freeflow test` to probe a relay; relay latency tracking with health badges in `/freeflow list`.
|
|
211
|
+
- Guided deploy with context picker + confirmation; post-deploy health check.
|
|
212
|
+
- Status clarity: current mode + state file path; log text filter; per-relay usage counters; throttled roll notifications.
|
|
213
|
+
|
|
214
|
+
### Reliability
|
|
215
|
+
|
|
216
|
+
- Relay state write-protection: before every save, the current state is snapshotted to `.bak`; if the main file is corrupted or missing, the backup is recovered automatically.
|
|
217
|
+
- New-user flow never seeds a fake relay; starts in direct mode with an empty pool.
|
|
218
|
+
|
|
219
|
+
## 1.5.1 - 2026-08-28
|
|
220
|
+
|
|
221
|
+
- Edge-sweep fixes: port 28180 with legacy 18080 dual-probe auto-migration, OMP/Pi compatibility.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-freeflow 🌊
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **26 free models. Up to 1M context. Zero API keys. Infinite scale via your own relay pool.**
|
|
4
4
|
|
|
5
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
|
|
|
@@ -18,7 +18,7 @@ Join devs bypassing rate limits with their own relay pools. BYO, add as many as
|
|
|
18
18
|
|
|
19
19
|
| Feature | Description | Value | Cost |
|
|
20
20
|
| :--- | :--- | :--- | :--- |
|
|
21
|
-
| **
|
|
21
|
+
| **26 Curated Free Models** | 7 OpenCode Zen + 19 KiloCode Gateway models, up to 1M context & 512K output | Ceiling Unlocked | **$0** |
|
|
22
22
|
| **BYO Relay Pool** | Round-robin load balancing across your Cloudflare Workers & Vercel Edges | Zero Rate Limits | **$0** (your free tiers) |
|
|
23
23
|
| **Adaptive Health & Error Detection** | Auto-cooldown on 429 rate limits, 504 timeouts, and socket drops | 0ms Wasted Latency | **$0** |
|
|
24
24
|
| **Stream Truncation Resilience** | Stateful SSE terminal tracking (`response.failed` / `response.incomplete` injection) | Zero Host Crashes | **$0** |
|
|
@@ -32,7 +32,7 @@ Philosophy: **Thin by design.** We only ship model list + relay proxy + log. Hos
|
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
35
|
-
###
|
|
35
|
+
### 26 Curated Models, One Command
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
/model → freeflow → pick
|
|
@@ -51,7 +51,7 @@ Optimized for deep reasoning, long-horizon coding & autonomous agentic workflows
|
|
|
51
51
|
| `big-pickle` | Big Pickle | **200K** (200.000) | **32K** (32.000) | `high / max` | ❌ |
|
|
52
52
|
| `ling-3.0-flash-fin-free` | Inclusion AI | **262K** (262.144) | **131K** (131.072) | `minimal … xhigh` | ❌ |
|
|
53
53
|
|
|
54
|
-
#### KiloCode Gateway (
|
|
54
|
+
#### KiloCode Gateway (19 Models), OpenRouter Compatible
|
|
55
55
|
Keyless access with `Bearer kilo-free`. Clean slash-free and colon-free CLI aliases supported.
|
|
56
56
|
|
|
57
57
|
| Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
|
|
@@ -70,8 +70,10 @@ Keyless access with `Bearer kilo-free`. Clean slash-free and colon-free CLI alia
|
|
|
70
70
|
| `openrouter` (`openrouter/free`) | OpenRouter Free | **200K** (200.000) | **65K** (65.536) | `minimal…xhigh`\* | ✅ |
|
|
71
71
|
| `content-safety` (`nvidia/...:free`) | NVIDIA | **128K** (128.000) | **8K** (8.192) | ❌ *(non-thinking)* | ✅ |
|
|
72
72
|
| `ling-3.0-flash-fin` (`inclusionai/ling-3.0-flash-fin:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
|
|
73
|
-
| `inkling` (`thinkingmachines/inkling:free`) | Thinking Machines | **1M** (1.048.576) | **262K** (262.144) | `minimal…xhigh`\* | ✅ |
|
|
74
73
|
| `ling-3.0-flash-sante` (`inclusionai/ling-3.0-flash-sante:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ❌ |
|
|
74
|
+
| `nex-n2.5-pro` (`nex-agi/nex-n2.5-pro:free`) | Nex AGI | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
|
|
75
|
+
| `nex-n2.5-mini` (`nex-agi/nex-n2.5-mini:free`) | Nex AGI | **262K** (262.144) | **235K** (235.929) | `minimal…xhigh`\* | ✅ |
|
|
76
|
+
| `ling-3.0-flash-vl` (`inclusionai/ling-3.0-flash-vl:free`) | Inclusion AI | **262K** (262.144) | **32K** (32.768) | `minimal…xhigh`\* | ✅ |
|
|
75
77
|
| `inkling-small` (`thinkingmachines/inkling-small:free`) | Thinking Machines | **1M** (1.048.576) | **262K** (262.144) | `minimal…xhigh`\* | ✅ |
|
|
76
78
|
|
|
77
79
|
\* 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.
|
|
@@ -340,7 +342,7 @@ pnpm smoke # verifies extensions/index.ts loads without crashing
|
|
|
340
342
|
```
|
|
341
343
|
src/
|
|
342
344
|
├── index.ts # extension entry, lifecycle hooks
|
|
343
|
-
├── models.ts #
|
|
345
|
+
├── models.ts # 26-model catalog definitions
|
|
344
346
|
├── catalog.ts # model catalog cache (24h disk)
|
|
345
347
|
├── proxy.ts # local proxy server (127.0.0.1:28180)
|
|
346
348
|
├── relay.ts # relay selection & round-robin
|
package/package.json
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-freeflow",
|
|
3
|
-
"type": "module",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"description": "Thin provider for OMP/Pi — model list + dumb relay proxy + log; host pi-ai owns thinking/normalization",
|
|
6
|
-
"main": "extensions/index.ts",
|
|
7
|
-
"types": "src/index.ts",
|
|
8
|
-
"keywords": [
|
|
9
|
-
"pi-package",
|
|
10
|
-
"pi-extension",
|
|
11
|
-
"oh-my-pi",
|
|
12
|
-
"omp",
|
|
13
|
-
"free-models",
|
|
14
|
-
"opencode",
|
|
15
|
-
"kilocode",
|
|
16
|
-
"ai-models",
|
|
17
|
-
"relay"
|
|
18
|
-
],
|
|
19
|
-
"author": "trefeon",
|
|
20
|
-
"license": "MIT",
|
|
21
|
-
"repository": {
|
|
22
|
-
"type": "git",
|
|
23
|
-
"url": "git+https://github.com/trefeon/pi-freeflow.git"
|
|
24
|
-
},
|
|
25
|
-
"homepage": "https://github.com/trefeon/pi-freeflow#readme",
|
|
26
|
-
"engines": {
|
|
27
|
-
"node": ">=22.19.0"
|
|
28
|
-
},
|
|
29
|
-
"omp": {
|
|
30
|
-
"extensions": [
|
|
31
|
-
"./extensions"
|
|
32
|
-
]
|
|
33
|
-
},
|
|
34
|
-
"pi": {
|
|
35
|
-
"extensions": [
|
|
36
|
-
"./extensions"
|
|
37
|
-
]
|
|
38
|
-
},
|
|
39
|
-
"files": [
|
|
40
|
-
"extensions",
|
|
41
|
-
"src",
|
|
42
|
-
"README.md",
|
|
43
|
-
"CHANGELOG.md",
|
|
44
|
-
"LICENSE"
|
|
45
|
-
],
|
|
46
|
-
"scripts": {
|
|
47
|
-
"test": "node --experimental-strip-types --import ./test/setup.mjs --test --test-concurrency=1 test/**/*.test.ts",
|
|
48
|
-
"typecheck": "tsc --noEmit",
|
|
49
|
-
"smoke": "node --experimental-strip-types -e \"import('./extensions/index.ts').then(() => console.log('✓ Smoke test passed: extensions/index.ts loaded successfully')).catch(err => { console.error(err); process.exit(1); })\"",
|
|
50
|
-
"changeset": "changeset",
|
|
51
|
-
"docs:dev": "vitepress dev docs",
|
|
52
|
-
"docs:build": "vitepress build docs"
|
|
53
|
-
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"@changesets/cli": "^2.27.0",
|
|
56
|
-
"@types/node": "^22.13.9",
|
|
57
|
-
"typescript": "^5.8.2",
|
|
58
|
-
"vitepress": "^1.6.4"
|
|
59
|
-
},
|
|
60
|
-
"dependencies": {}
|
|
61
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-freeflow",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.12.0",
|
|
5
|
+
"description": "Thin provider for OMP/Pi — model list + dumb relay proxy + log; host pi-ai owns thinking/normalization",
|
|
6
|
+
"main": "extensions/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"pi-package",
|
|
10
|
+
"pi-extension",
|
|
11
|
+
"oh-my-pi",
|
|
12
|
+
"omp",
|
|
13
|
+
"free-models",
|
|
14
|
+
"opencode",
|
|
15
|
+
"kilocode",
|
|
16
|
+
"ai-models",
|
|
17
|
+
"relay"
|
|
18
|
+
],
|
|
19
|
+
"author": "trefeon",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/trefeon/pi-freeflow.git"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/trefeon/pi-freeflow#readme",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22.19.0"
|
|
28
|
+
},
|
|
29
|
+
"omp": {
|
|
30
|
+
"extensions": [
|
|
31
|
+
"./extensions"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"pi": {
|
|
35
|
+
"extensions": [
|
|
36
|
+
"./extensions"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"extensions",
|
|
41
|
+
"src",
|
|
42
|
+
"README.md",
|
|
43
|
+
"CHANGELOG.md",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"test": "node --experimental-strip-types --import ./test/setup.mjs --test --test-concurrency=1 test/**/*.test.ts",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"smoke": "node --experimental-strip-types -e \"import('./extensions/index.ts').then(() => console.log('✓ Smoke test passed: extensions/index.ts loaded successfully')).catch(err => { console.error(err); process.exit(1); })\"",
|
|
50
|
+
"changeset": "changeset",
|
|
51
|
+
"docs:dev": "vitepress dev docs",
|
|
52
|
+
"docs:build": "vitepress build docs"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@changesets/cli": "^2.27.0",
|
|
56
|
+
"@types/node": "^22.13.9",
|
|
57
|
+
"typescript": "^5.8.2",
|
|
58
|
+
"vitepress": "^1.6.4"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {}
|
|
61
|
+
}
|
package/src/catalog.ts
CHANGED
|
@@ -40,6 +40,7 @@ export const DEAD_MODEL_IDS = new Set<string>([
|
|
|
40
40
|
"laguna-s-2.1-free",
|
|
41
41
|
"minimax/minimax-m2.7:free",
|
|
42
42
|
"minimax/minimax-m3:free",
|
|
43
|
+
"thinkingmachines/inkling:free",
|
|
43
44
|
]);
|
|
44
45
|
/**
|
|
45
46
|
* Free-tier allowlist for anything entering the picker via network or stale disk.
|
|
@@ -76,7 +77,7 @@ export function sanitizeCatalogModels(models: RegisteredModel[]): RegisteredMode
|
|
|
76
77
|
}
|
|
77
78
|
/**
|
|
78
79
|
* In-memory cache of currently active/available free models.
|
|
79
|
-
* Initialized with all
|
|
80
|
+
* Initialized with all 26 verified models for 0ms instant availability.
|
|
80
81
|
*/
|
|
81
82
|
let aliveCatalog: RegisteredModel[] = ALL_MODELS.map((m) => ({
|
|
82
83
|
...m,
|
|
@@ -399,6 +400,6 @@ export async function refreshCatalog(force = false): Promise<RegisteredModel[]>
|
|
|
399
400
|
} catch (err) {
|
|
400
401
|
logDebug("Failed reading stale catalog cache", { error: String(err) });
|
|
401
402
|
}
|
|
402
|
-
// No valid cache — return in-memory static
|
|
403
|
+
// No valid cache — return in-memory static 26 (host will refresh if needed)
|
|
403
404
|
return aliveCatalog;
|
|
404
405
|
}
|
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 26 free models (7 OpenCode Zen + 19 KiloCode Gateway) 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
|
package/src/models.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Static model definitions and upstream routing catalogs for pi-freeflow
|
|
3
3
|
*
|
|
4
|
-
* Defines the
|
|
4
|
+
* Defines the 26 verified free models:
|
|
5
5
|
* - 7 OpenCode Zen models (2 Responses API + 5 Chat Completions)
|
|
6
|
-
* -
|
|
6
|
+
* - 19 KiloCode Keyless Gateway models (18 OpenRouter format + 1 Standard format)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { ModelDef, ThinkingLevelMap, Upstream } from "./types.ts";
|
|
@@ -290,11 +290,21 @@ export const KILO_MODELS: ModelDef[] = [
|
|
|
290
290
|
thinkingLevelMap: KILO_REASONING_MAP,
|
|
291
291
|
},
|
|
292
292
|
{
|
|
293
|
-
id: "
|
|
294
|
-
name: "
|
|
293
|
+
id: "nex-agi/nex-n2.5-pro:free",
|
|
294
|
+
name: "Nex N2.5 Pro",
|
|
295
295
|
reasoning: true,
|
|
296
|
-
contextWindow:
|
|
297
|
-
maxTokens:
|
|
296
|
+
contextWindow: 262_144,
|
|
297
|
+
maxTokens: 235_929,
|
|
298
|
+
input: ["text", "image"],
|
|
299
|
+
thinkingFormat: "openrouter",
|
|
300
|
+
thinkingLevelMap: KILO_REASONING_MAP,
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
id: "nex-agi/nex-n2.5-mini:free",
|
|
304
|
+
name: "Nex N2.5 Mini",
|
|
305
|
+
reasoning: true,
|
|
306
|
+
contextWindow: 262_144,
|
|
307
|
+
maxTokens: 235_929,
|
|
298
308
|
input: ["text", "image"],
|
|
299
309
|
thinkingFormat: "openrouter",
|
|
300
310
|
thinkingLevelMap: KILO_REASONING_MAP,
|
|
@@ -319,6 +329,16 @@ export const KILO_MODELS: ModelDef[] = [
|
|
|
319
329
|
thinkingFormat: "openrouter",
|
|
320
330
|
thinkingLevelMap: KILO_REASONING_MAP,
|
|
321
331
|
},
|
|
332
|
+
{
|
|
333
|
+
id: "inclusionai/ling-3.0-flash-vl:free",
|
|
334
|
+
name: "Ling 3.0 Flash VL",
|
|
335
|
+
reasoning: true,
|
|
336
|
+
contextWindow: 262_144,
|
|
337
|
+
maxTokens: 32_768,
|
|
338
|
+
input: ["text", "image"],
|
|
339
|
+
thinkingFormat: "openrouter",
|
|
340
|
+
thinkingLevelMap: KILO_REASONING_MAP,
|
|
341
|
+
},
|
|
322
342
|
];
|
|
323
343
|
|
|
324
344
|
/**
|
|
@@ -329,7 +349,6 @@ export const KILO_MODELS: ModelDef[] = [
|
|
|
329
349
|
* - Hy3 = Tencent Hunyuan (not Alibaba Qwen) → removed qwen3-coder alias
|
|
330
350
|
*/
|
|
331
351
|
export const MODEL_ALIASES: Record<string, string> = {
|
|
332
|
-
// Kilo Gateway — slash-free & colon-free clean aliases (one per model)
|
|
333
352
|
"dots-3-note-preview": "dots-studio/dots-3-note-preview:free",
|
|
334
353
|
"step-3.7-flash": "stepfun/step-3.7-flash:free",
|
|
335
354
|
"nemotron-3-nano-omni": "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free",
|
|
@@ -341,7 +360,9 @@ export const MODEL_ALIASES: Record<string, string> = {
|
|
|
341
360
|
"content-safety": "nvidia/nemotron-3.5-content-safety:free",
|
|
342
361
|
"ling-3.0-flash-fin": "inclusionai/ling-3.0-flash-fin:free",
|
|
343
362
|
"ling-3.0-flash-sante": "inclusionai/ling-3.0-flash-sante:free",
|
|
344
|
-
"
|
|
363
|
+
"ling-3.0-flash-vl": "inclusionai/ling-3.0-flash-vl:free",
|
|
364
|
+
"nex-n2.5-pro": "nex-agi/nex-n2.5-pro:free",
|
|
365
|
+
"nex-n2.5-mini": "nex-agi/nex-n2.5-mini:free",
|
|
345
366
|
"inkling-small": "thinkingmachines/inkling-small:free",
|
|
346
367
|
// provider-prefixed short aliases (slash-normalized)
|
|
347
368
|
"laguna-s-2.1:free": "poolside/laguna-s-2.1:free",
|
|
@@ -357,7 +378,6 @@ export function resolveCanonicalModelId(id: string): string {
|
|
|
357
378
|
const clean = (id || "").trim();
|
|
358
379
|
return MODEL_ALIASES[clean] || clean;
|
|
359
380
|
}
|
|
360
|
-
|
|
361
381
|
/**
|
|
362
382
|
* Set of all KiloCode model IDs (including aliases) for fast lookup
|
|
363
383
|
*/
|
|
@@ -369,7 +389,7 @@ export const KILO_MODEL_IDS = new Set<string>([
|
|
|
369
389
|
]);
|
|
370
390
|
|
|
371
391
|
/**
|
|
372
|
-
* Combined list of all
|
|
392
|
+
* Combined list of all 26 static free models (canonical)
|
|
373
393
|
*/
|
|
374
394
|
export const ALL_MODELS: ModelDef[] = [...OPENCODE_MODELS, ...KILO_MODELS];
|
|
375
395
|
|
package/src/relay.ts
CHANGED
|
@@ -155,6 +155,28 @@ export async function relayFetch(
|
|
|
155
155
|
}
|
|
156
156
|
break;
|
|
157
157
|
}
|
|
158
|
+
// Relay payload cap hit (413: request exceeds host payload limit):
|
|
159
|
+
// Not a relay health signal, so no failure marking — try the next
|
|
160
|
+
// relay (a different host may accept it), else the direct fallback.
|
|
161
|
+
if (res.status === 413) {
|
|
162
|
+
lastResponse?.body?.cancel().catch(() => {});
|
|
163
|
+
lastResponse = res;
|
|
164
|
+
log(
|
|
165
|
+
"warn",
|
|
166
|
+
`relay ${targetUrl} hit HTTP 413 payload limit in ${elapsed}s — trying next path`,
|
|
167
|
+
{ upstream: url, sizeKB: bodySizeKB },
|
|
168
|
+
rid,
|
|
169
|
+
);
|
|
170
|
+
const now = Date.now();
|
|
171
|
+
if (now - lastRollNotify > ROLL_NOTIFY_MS) {
|
|
172
|
+
lastRollNotify = now;
|
|
173
|
+
const ui = getStatusUi();
|
|
174
|
+
if (ui?.notify) {
|
|
175
|
+
ui.notify(`relay ${shortRelayLabel(targetUrl)} hit payload limit — trying next path`, "warning");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
158
180
|
|
|
159
181
|
// Relay host infrastructure 404 (e.g. Vercel DEPLOYMENT_NOT_FOUND or non-JSON 404):
|
|
160
182
|
// When a relay URL is deleted, misconfigured, or has no deployment, Vercel/Cloudflare
|