pi-freeflow 1.3.9 → 1.4.1

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
@@ -14,71 +14,64 @@ Thin by design: model list + dumb relay + log. Host `pi-ai` owns thinking, norma
14
14
 
15
15
  ---
16
16
 
17
- ### Why FreeFlow?
18
-
19
- You love Pi. You love free models. You hate:
20
-
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
25
-
26
- **FreeFlow fixes all three in 17 files, 115KB.**
27
-
28
- ### Features
29
-
30
- | What You Get | Value | Cost |
31
- | :--- | :--- | :--- |
32
- | **23 Curated Free Models** — 9 OpenCode Zen + 14 Kilo Gateway, 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
- | **Adaptive Health & Error Detection** — Auto-cooldown on 429/504/socket drops, instant roll to healthy relays | Self-healing | **$0** |
35
- | **Dumb Proxy That Never Breaks** — `127.0.0.1:18080`, host-normalized, pathname-guarded `/v1/models` | 100% uptime | **$0** |
36
- | **Real Logs** — `~/.pi/agent/pi-freeflow.log`, 5MB rotate, debug toggle | Observable | **$0** |
17
+ ### Features at a Glance
18
+
19
+ | Feature | Description | Value | Cost |
20
+ | :--- | :--- | :--- | :--- |
21
+ | **23 Curated Free Models** | 9 OpenCode Zen + 14 KiloCode Gateway models, up to 1M context & 512K output | Ceiling Unlocked | **$0** |
22
+ | **BYO Relay Pool** | Round-robin load balancing across your Cloudflare Workers & Vercel Edges | Zero Rate Limits | **$0** (your free tiers) |
23
+ | **Adaptive Health & Error Detection** | Auto-cooldown on 429 rate limits, 504 timeouts, and socket drops | 0ms Wasted Latency | **$0** |
24
+ | **Stream Truncation Resilience** | Stateful SSE terminal tracking (`response.failed` / `response.incomplete` injection) | Zero Host Crashes | **$0** |
25
+ | **Smart Model Aliasing** | Clean slash-free & colon-free CLI model names compatible with thinking selectors | DX Optimized | **$0** |
26
+ | **Auto-Enabled on Session** | Relay stays enabled in `auto` mode on session start and model switch | Zero Friction | **$0** |
27
+ | **Interactive CLI Management** | 10+ `/freeflow` subcommands (`status`, `list`, `use`, `add`, `label`, `remove`, `deploy`, `logs`, `debug`) | Full Control | **$0** |
28
+ | **Dumb Proxy That Never Breaks** | `127.0.0.1:18080`, host-normalized, pathname-guarded `/v1/models` | 100% Uptime | **$0** |
29
+ | **Observable Real Logs** | `~/.pi/agent/pi-freeflow.log`, 5MB auto-rotation, real-time debug toggle | Observable | **$0** |
37
30
 
38
31
  Philosophy: **Thin by design.** We only ship model list + relay proxy + log. Host owns thinking & normalization.
39
32
 
40
33
  ---
41
34
 
42
- ### 23 Models — One Command
35
+ ### 23 Curated Models — One Command
43
36
 
44
37
  ```bash
45
38
  /model → freeflow → pick
46
39
  ```
47
40
 
48
- #### OpenCode Zen (9) — Responses & Chat API
49
- Best for long-context reasoning & autonomous agentic tasks.
41
+ #### OpenCode Zen (9 Models) — Responses & Chat API
42
+ Optimized for deep reasoning, long-horizon coding & autonomous agentic workflows.
50
43
 
51
44
  | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
52
45
  | :--- | :--- | :--- | :--- | :--- | :--- |
53
- | `muse-spark-1.2-contributor-free` | Meta Superintelligence Labs | 1M | 131K | `minimal → max` | ✅ |
54
- | `x-preview-f-free` | Ox Alpha | 1M | 131K | `low / high / max` | ✅ |
55
- | `mimo-v2.5-free` | Xiaomi MiMo | 1M | 131K | `low / medium / high` | ✅ |
56
- | `deepseek-v4-flash-free` | DeepSeek | 1M | 384K | `minimal → max` | ❌ |
57
- | `laguna-s-2.1-free` | Poolside | 1M | 131K | `minimal → max` | ❌ |
58
- | `nemotron-3.5-lightning-free` | NVIDIA | 1M | 262K | `minimal → max` | ❌ |
59
- | `nemotron-3-ultra-free` | NVIDIA | 1M | 128K | `minimal → max` | ❌ |
60
- | `hy3-free` | Tencent Hunyuan | 262K | 262K | `minimal → max` | ❌ |
61
- | `big-pickle` | Big Pickle | 200K | 32K | `high / max` | ❌ |
62
-
63
- #### Kilo Gateway (14) — OpenRouter Compatible
64
- Keyless access with `Bearer kilo-free`. Short slash-free & colon-free CLI aliases supported.
46
+ | `muse-spark-1.2-contributor-free` | Meta Superintelligence Labs | **1M** (1.048.576) | **131K** (131.072) | `minimal → max` | ✅ |
47
+ | `x-preview-f-free` | Ox Alpha | **1M** (1.048.576) | **131K** (131.072) | `low / high / max` | ✅ |
48
+ | `mimo-v2.5-free` | Xiaomi MiMo | **1M** (1.048.576) | **131K** (131.072) | `low / medium / high` | ✅ |
49
+ | `deepseek-v4-flash-free` | DeepSeek | **1M** (1.000.000) | **384K** (384.000) | `minimal → max` | ❌ |
50
+ | `laguna-s-2.1-free` | Poolside | **1M** (1.048.576) | **131K** (131.072) | `minimal → max` | ❌ |
51
+ | `nemotron-3.5-lightning-free` | NVIDIA | **1M** (1.000.000) | **262K** (262.144) | `minimal → max` | ❌ |
52
+ | `nemotron-3-ultra-free` | NVIDIA | **1M** (1.000.000) | **128K** (128.000) | `minimal → max` | ❌ |
53
+ | `hy3-free` | Tencent Hunyuan | **262K** (262.144) | **262K** (262.144) | `minimal → max` | ❌ |
54
+ | `big-pickle` | Big Pickle | **200K** (200.000) | **32K** (32.000) | `high / max` | ❌ |
55
+
56
+ #### KiloCode Gateway (14 Models) — OpenRouter Compatible
57
+ Keyless access with `Bearer kilo-free`. Clean slash-free and colon-free CLI aliases supported.
65
58
 
66
59
  | Model ID | Creator / Lab | Context | Max Output | Thinking | Vision |
67
60
  | :--- | :--- | :--- | :--- | :--- | :--- |
68
- | `dots-3-note-preview` (`dots-studio/...:free`) | Dots Studio | 512K | 512K | `openrouter` (auto) | ✅ |
69
- | `step-3.7-flash` (`stepfun/...:free`) | StepFun | 262K | 262K | `low / medium / high` | ✅ |
70
- | `nemotron-3-nano-omni` (`nvidia/...:free`) | NVIDIA | 256K | 65K | `openrouter` (auto) | ✅ |
71
- | `nemotron-3-ultra-550b` (`nvidia/...:free`) | NVIDIA | 1M | 65K | `openrouter` (auto) | ❌ |
72
- | `nemotron-3.5-lightning` (`nvidia/...:free`) | NVIDIA | 1M | 131K | `openrouter` (auto) | ❌ |
73
- | `nemotron-3-super` (`nvidia/...:free`) | NVIDIA | 262K | 262K | `openrouter` (auto) | ❌ |
74
- | `hy3` (`tencent/hy3:free`) | Tencent Hunyuan | 262K | 262K | `openrouter` (auto) | ❌ |
75
- | `north-mini-code` (`cohere/...:free`) | Cohere | 256K | 64K | `openrouter` (auto) | ❌ |
76
- | `laguna-s-2.1` (`poolside/...:free`) | Poolside | 1M | 131K | `openrouter` (auto) | ❌ |
77
- | `laguna-xs-2.1` (`poolside/...:free`) | Poolside | 262K | 32K | `openrouter` (auto) | ❌ |
78
- | `lfm-2.5` (`liquid/lfm-2.5-2.6b:free`) | Liquid AI | 128K | 32K | `openrouter` (auto) | ❌ |
79
- | `kilo-auto` (`kilo-auto/free`) | Kilo Gateway Auto | 256K | 10K | ❌ | ❌ |
80
- | `openrouter` (`openrouter/free`) | OpenRouter Free | 200K | 65K | ❌ | ✅ |
81
- | `content-safety` (`nvidia/...:free`) | NVIDIA | 128K | 8K | ❌ | ✅ |
61
+ | `dots-3-note-preview` (`dots-studio/...:free`) | Dots Studio | **512K** (512.000) | **512K** (512.000) | `openrouter` (auto) | ✅ |
62
+ | `step-3.7-flash` (`stepfun/...:free`) | StepFun | **262K** (262.144) | **262K** (262.144) | `low / medium / high` | ✅ |
63
+ | `nemotron-3-nano-omni` (`nvidia/...:free`) | NVIDIA | **256K** (256.000) | **65K** (65.536) | `openrouter` (auto) | ✅ |
64
+ | `nemotron-3-ultra-550b` (`nvidia/...:free`) | NVIDIA | **1M** (1.000.000) | **65K** (65.536) | `openrouter` (auto) | ❌ |
65
+ | `nemotron-3.5-lightning` (`nvidia/...:free`) | NVIDIA | **1M** (1.000.000) | **131K** (131.072) | `openrouter` (auto) | ❌ |
66
+ | `nemotron-3-super` (`nvidia/...:free`) | NVIDIA | **262K** (262.144) | **262K** (262.144) | `openrouter` (auto) | ❌ |
67
+ | `hy3` (`tencent/hy3:free`) | Tencent Hunyuan | **262K** (262.144) | **262K** (262.144) | `openrouter` (auto) | ❌ |
68
+ | `north-mini-code` (`cohere/...:free`) | Cohere | **256K** (256.000) | **64K** (64.000) | `openrouter` (auto) | ❌ |
69
+ | `laguna-s-2.1` (`poolside/...:free`) | Poolside | **1M** (1.048.576) | **131K** (131.072) | `openrouter` (auto) | ❌ |
70
+ | `laguna-xs-2.1` (`poolside/...:free`) | Poolside | **262K** (262.144) | **32K** (32.768) | `openrouter` (auto) | ❌ |
71
+ | `lfm-2.5` (`liquid/lfm-2.5-2.6b:free`) | Liquid AI | **128K** (128.000) | **32K** (32.768) | `openrouter` (auto) | ❌ |
72
+ | `kilo-auto` (`kilo-auto/free`) | Kilo Gateway Auto | **256K** (256.000) | **10K** (10.000) | ❌ *(non-thinking)* | ❌ |
73
+ | `openrouter` (`openrouter/free`) | OpenRouter Free | **200K** (200.000) | **65K** (65.536) | ❌ *(non-thinking)* | ✅ |
74
+ | `content-safety` (`nvidia/...:free`) | NVIDIA | **128K** (128.000) | **8K** (8.192) | ❌ *(non-thinking)* | ✅ |
82
75
 
83
76
  ---
84
77
 
@@ -89,17 +82,36 @@ You → 127.0.0.1:18080 (dumb proxy, host-normalized) → x-relay-target → N e
89
82
  ↑ host already normalized thinking → proxy just forwards
90
83
  ```
91
84
 
92
- - **Round-robin per request** — 10 parallel subagents hit N different egress IPs (your pool size). No thundering herd.
93
- - **Adaptive Health & Error Cooldown** Relays hitting 429, 504, or network socket drops enter automatic cooldown (30-90s) and move behind healthy candidates.
94
- - **Seamless 429 roll** `429 / 502 / 503 / 504` → instant roll to next relay, never 429 to agent.
95
- - **Exhausted? Direct fallback** If all relays are 429 (global limit), transparent direct fetch. Host shows rate limit only when truly global.
96
- - **No live catalog fetch** 24h `DISK_CACHE_ONLY`, never fetch from subagent no `Unable to connect`.
97
- - **Stream Truncation Resilience** Detects SSE terminal events; handles premature stream closure with clean termination.
85
+ 1. **Per-Request Round-Robin**: 10 parallel subagents hit N different egress IPs (your pool size). No thundering herd.
86
+ 2. **Adaptive Health & Error Cooldown**: Relays hitting 429, 504, or socket disconnects enter temporary cooldown (30-90s) and automatically move behind healthy candidates. Healthy relays handle traffic with 0ms wasted delay.
87
+ 3. **Seamless 429 Roll**: `429 / 502 / 503 / 504` → instant roll to next relay, never 429 to agent.
88
+ 4. **Stream Truncation Resilience**: Stateful SSE terminal tracking prevents fatal unhandled stream closed errors when connections drop.
89
+ 5. **Direct Fallback Safety Net**: If all relays in the pool are exhausted, transparent direct fetch to upstream.
90
+ 6. **Zero Subagent Connect Errors**: 24h `DISK_CACHE_ONLY` model catalog avoids subagents hammering remote catalogs.
98
91
 
99
92
  You bring the relays (free tiers). We bring the rolling.
100
93
 
101
94
  ---
102
95
 
96
+ ### Interactive Commands Reference (`/freeflow`)
97
+
98
+ Manage your relay pool directly from the OMP / Pi terminal:
99
+
100
+ ```bash
101
+ /freeflow status # View active relay, pool status, and candidates
102
+ /freeflow list # List all relays with real-time health badges (✓ / ⚠️ [cooling])
103
+ /freeflow use <url|index|label> # Switch active relay
104
+ /freeflow add <url> [label] # Add new relay to the pool
105
+ /freeflow label <index|url> <name># Assign a friendly label to a relay
106
+ /freeflow remove <index|url|label># Remove a relay from the pool
107
+ /freeflow on | off | auto # Toggle relay mode (auto = enabled for freeflow)
108
+ /freeflow deploy # Guided auto-deploy 6 Vercel Edge relays (in-memory token)
109
+ /freeflow logs [lines] # Inspect recent proxy logs
110
+ /freeflow debug on | off # Toggle full HTTP lifecycle debug logging
111
+ ```
112
+
113
+ ---
114
+
103
115
  ### Quick Start — 30 Seconds
104
116
 
105
117
  #### 1. Install
@@ -124,25 +136,26 @@ omp
124
136
 
125
137
  # or CLI
126
138
  omp -p --model freeflow/muse-spark-1.2-contributor-free "build me a SaaS"
139
+ # or with short alias & thinking level
140
+ omp -p --model freeflow/step-3.7-flash:high "solve this bug"
127
141
  ```
128
142
 
129
- #### 3. (Optional but 🔥) Add Your Free Relays
143
+ #### 3. Add Your Free Relays (Scale Infinitely)
130
144
 
131
- Scale infinitely. Default ships direct, add relays via `/freeflow use <url>`.
145
+ Default ships direct. Add relays via `/freeflow add <url> [label]`.
132
146
 
133
- **Option A: One Cloudflare Worker (100k req/day, no 25s timeout)**
147
+ **Option A: Cloudflare Workers (100k req/day, no 25s timeout)**
134
148
  1. Go to `dash.cloudflare.com` → Workers → Create → Deploy → Edit code
135
149
  2. Paste the Worker relay snippet from `/reference/worker-relay.js`
136
150
  3. Deploy and add it:
137
151
 
138
152
  ```bash
139
- omp → /freeflow use https://your.workers.dev
153
+ omp → /freeflow add https://your.workers.dev cf-worker-1
140
154
  ```
141
155
 
142
156
  **Option B: Six Vercel Edges (1M req/mo) — Auto Deploy**
143
157
  ```bash
144
158
  /freeflow deploy # prompts token in-memory, auto-adds to pool
145
- # or manual: vercel.json → api/relay.js
146
159
  ```
147
160
 
148
161
  **Verify your pool:**
@@ -153,7 +166,7 @@ omp → /freeflow use https://your.workers.dev
153
166
  cat ~/.pi/agent/pi-freeflow.log | tail -n 20
154
167
  ```
155
168
 
156
- Done. Subagents now follow parent proxy — `Unable to connect` is history.
169
+ ---
157
170
 
158
171
  ### Logs & Debugging
159
172
 
@@ -165,7 +178,9 @@ cat ~/.pi/agent/pi-freeflow.log | tail -n 50
165
178
  /freeflow debug on
166
179
  ```
167
180
 
168
- Log rotation at 5MB. Clean, parseable, real-time.
181
+ Log rotation at 5MB. Clean, parseable, real-time HTTP lifecycle tracking.
182
+
183
+ ---
169
184
 
170
185
  ### Philosophy: Thin vs Fat
171
186
 
@@ -178,6 +193,8 @@ Log rotation at 5MB. Clean, parseable, real-time.
178
193
 
179
194
  **Result: <500 LOC core, 39 tests PASS, typecheck PASS.**
180
195
 
196
+ ---
197
+
181
198
  ### FAQ
182
199
 
183
200
  **Do I need API keys?**
@@ -195,6 +212,8 @@ Deleted in 1.3.0. If zai/qwen/deepseek thinking broke before, it's fixed now bec
195
212
  **Why is context free?**
196
213
  We use OpenCode Zen & Kilo free tiers. You pay only with your own Cloudflare/Vercel free tiers for egress.
197
214
 
215
+ ---
216
+
198
217
  ### Contributing
199
218
 
200
219
  > "I shipped 10 parallel subagents on 1M context, zero keys, zero 429s. FreeFlow did the rolling, Pi did the thinking."
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-freeflow",
3
3
  "type": "module",
4
- "version": "1.3.9",
4
+ "version": "1.4.1",
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/index.ts CHANGED
@@ -139,11 +139,11 @@ export default async function (pi: ExtensionAPI): Promise<void> {
139
139
 
140
140
  // 3. Instant 0ms Static Catalog Registration
141
141
  // Register static models immediately on boot so Pi/OMP picker is populated with zero latency!
142
- const registeredCatalog: RegisteredModel[] = getAllRegisteredModels().map((m) => ({
142
+ const registeredCatalog: RegisteredModel[] = ALL_MODELS.map((m) => ({
143
143
  ...m,
144
144
  source: KILO_MODEL_IDS.has(m.id) ? "kilo" : "opencode",
145
145
  }));
146
- setAliveCatalog(ALL_MODELS.map((m) => ({ ...m, source: KILO_MODEL_IDS.has(m.id) ? "kilo" : "opencode" })));
146
+ setAliveCatalog(registeredCatalog);
147
147
  pi.registerProvider(
148
148
  "freeflow",
149
149
  buildProviderConfig(registeredCatalog, actualPort),
package/src/models.ts CHANGED
@@ -357,36 +357,29 @@ export const KILO_MODEL_IDS = new Set<string>([
357
357
  ]);
358
358
 
359
359
  /**
360
- * Combined list of all 23 static free models
360
+ * Combined list of all 23 static free models (canonical)
361
361
  */
362
362
  export const ALL_MODELS: ModelDef[] = [...OPENCODE_MODELS, ...KILO_MODELS];
363
363
 
364
364
  /**
365
365
  * Map of model ID -> ModelDef
366
366
  */
367
- export const MODEL_MAP = new Map<string, ModelDef>([
368
- ...ALL_MODELS.map((m): [string, ModelDef] => [m.id, m]),
369
- ...Object.entries(MODEL_ALIASES).map(([aliasId, canonicalId]): [string, ModelDef] => {
370
- const base = ALL_MODELS.find((m) => m.id === canonicalId);
371
- return [
372
- aliasId,
373
- base
374
- ? { ...base, id: aliasId }
375
- : { id: aliasId, name: aliasId, reasoning: false, contextWindow: 200_000, maxTokens: 32_000, input: ["text"] },
376
- ];
377
- }),
378
- ]);
367
+ export const MODEL_MAP = new Map<string, ModelDef>(
368
+ ALL_MODELS.map((m): [string, ModelDef] => [m.id, m]),
369
+ );
370
+
379
371
  /**
380
- * Lookup a model definition by ID
372
+ * Get full list of registered canonical models for Pi/OMP provider registration
381
373
  */
382
- export function getModelDef(id: string): ModelDef | undefined {
383
- return MODEL_MAP.get(id) || MODEL_MAP.get(resolveCanonicalModelId(id));
374
+ export function getAllRegisteredModels(): ModelDef[] {
375
+ return ALL_MODELS;
384
376
  }
377
+
385
378
  /**
386
- * Get full list of registered models including CLI aliases
379
+ * Lookup a model definition by ID (supporting alias fallback)
387
380
  */
388
- export function getAllRegisteredModels(): ModelDef[] {
389
- return Array.from(MODEL_MAP.values());
381
+ export function getModelDef(id: string): ModelDef | undefined {
382
+ return MODEL_MAP.get(id) || MODEL_MAP.get(resolveCanonicalModelId(id));
390
383
  }
391
384
 
392
385