pi-freeflow 1.4.9 → 1.4.10
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 +31 -3
- package/package.json +55 -55
- package/src/config.ts +1 -1
- package/src/index.ts +1 -1
- package/src/proxy.ts +3 -4
- package/src/stream-pipe.ts +2 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Join devs bypassing rate limits with their own relay pools. BYO, add as many as
|
|
|
25
25
|
| **Smart Model Aliasing** | Clean slash-free & colon-free CLI model names compatible with thinking selectors | DX Optimized | **$0** |
|
|
26
26
|
| **Auto-Enabled on Session** | Relay stays enabled in `auto` mode on session start and model switch | Zero Friction | **$0** |
|
|
27
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:
|
|
28
|
+
| **Dumb Proxy That Never Breaks** | `127.0.0.1:28180`, host-normalized, pathname-guarded `/v1/models` | 100% Uptime | **$0** |
|
|
29
29
|
| **Observable Real Logs** | `~/.pi/agent/pi-freeflow.log`, 5MB auto-rotation, real-time debug toggle | Observable | **$0** |
|
|
30
30
|
|
|
31
31
|
Philosophy: **Thin by design.** We only ship model list + relay proxy + log. Host owns thinking & normalization.
|
|
@@ -78,7 +78,7 @@ Keyless access with `Bearer kilo-free`. Clean slash-free and colon-free CLI alia
|
|
|
78
78
|
### How It Works: BYO Relays, Zero Rate Limits
|
|
79
79
|
|
|
80
80
|
```
|
|
81
|
-
You → 127.0.0.1:
|
|
81
|
+
You → 127.0.0.1:28180 (dumb proxy, host-normalized) → x-relay-target → N egress IPs (your pool) → opencode.ai / api.kilo.ai
|
|
82
82
|
↑ host already normalized thinking → proxy just forwards
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -176,6 +176,34 @@ export default {
|
|
|
176
176
|
/freeflow deploy vercel # prompts token in-memory, auto-adds to pool
|
|
177
177
|
# or shorthand: /freeflow deploy
|
|
178
178
|
```
|
|
179
|
+
*Manual fallback:* Push 2 files (`api/relay.js` + `vercel.json`) to GitHub $\to$ Import on `vercel.com` $\to$ `/freeflow add https://your.vercel.app vercel-relay-1`
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
// api/relay.js
|
|
183
|
+
const ALLOWED_TARGETS = ["https://opencode.ai", "https://api.kilo.ai"];
|
|
184
|
+
export const config = { runtime: "edge" };
|
|
185
|
+
export default async function handler(req) {
|
|
186
|
+
const target = req.headers.get("x-relay-target");
|
|
187
|
+
const relayPath = req.headers.get("x-relay-path") || "/";
|
|
188
|
+
if (!target || !ALLOWED_TARGETS.includes(target.replace(/\/$/, ""))) {
|
|
189
|
+
return new Response(JSON.stringify({ error: "Forbidden target" }), { status: 403 });
|
|
190
|
+
}
|
|
191
|
+
const headers = new Headers(req.headers);
|
|
192
|
+
headers.delete("x-relay-target"); headers.delete("x-relay-path"); headers.delete("host");
|
|
193
|
+
const res = await fetch(target.replace(/\/$/, "") + relayPath, {
|
|
194
|
+
method: req.method,
|
|
195
|
+
headers,
|
|
196
|
+
body: req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined,
|
|
197
|
+
duplex: "half",
|
|
198
|
+
});
|
|
199
|
+
return new Response(res.body, { status: res.status, headers: res.headers });
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
// vercel.json
|
|
205
|
+
{ "rewrites": [{ "source": "/(.*)", "destination": "/api/relay" }] }
|
|
206
|
+
```
|
|
179
207
|
|
|
180
208
|
**Option C: Deno Deploy (100k req/day) — Auto Deploy**
|
|
181
209
|
```bash
|
|
@@ -279,7 +307,7 @@ src/
|
|
|
279
307
|
├── index.ts # extension entry, lifecycle hooks
|
|
280
308
|
├── models.ts # 21-model catalog definitions
|
|
281
309
|
├── catalog.ts # model catalog cache (24h disk)
|
|
282
|
-
├── proxy.ts # local proxy server (127.0.0.1:
|
|
310
|
+
├── proxy.ts # local proxy server (127.0.0.1:28180)
|
|
283
311
|
├── relay.ts # relay selection & round-robin
|
|
284
312
|
├── relay-state.ts # relay pool state, health tracking
|
|
285
313
|
├── rate-limiter.ts # adaptive cooldown on 429/504/socket errors
|
package/package.json
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-freeflow",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.4.10",
|
|
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.6.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
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"scripts": {
|
|
46
|
+
"test": "node --experimental-strip-types --test --test-concurrency=1 test/**/*.test.ts",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"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); })\""
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@earendil-works/pi-coding-agent": "^0.84.3",
|
|
52
|
+
"@types/node": "^22.13.9",
|
|
53
|
+
"typescript": "^5.8.2"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/config.ts
CHANGED
|
@@ -14,7 +14,7 @@ export const KILO_CHAT_URL = "https://api.kilo.ai/api/gateway/chat/completions";
|
|
|
14
14
|
export const OPENCODE_API_URL = `${UPSTREAM_OPENCODE}/v1`;
|
|
15
15
|
|
|
16
16
|
// ── Network & Server defaults ───────────────────────────────────────
|
|
17
|
-
export const DEFAULT_PORT =
|
|
17
|
+
export const DEFAULT_PORT = 28180;
|
|
18
18
|
export const HOST = "127.0.0.1";
|
|
19
19
|
export const DEFAULT_HOST = "127.0.0.1";
|
|
20
20
|
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* pi-freeflow — Modular, high-resiliency LLM extension for Pi & Oh My Pi (OMP)
|
|
3
3
|
*
|
|
4
4
|
* Provides access to 21 free models (7 OpenCode Zen + 14 KiloCode Gateway) with:
|
|
5
|
-
* - Single-port daemon reuse on
|
|
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
|
|
8
8
|
* - Per-model thinking/reasoning translation and streaming SSE pass-through
|
package/src/proxy.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Single-port local HTTP proxy and dynamic upstream router for pi-freeflow
|
|
3
3
|
*
|
|
4
|
-
* Provides loopback proxying on port
|
|
4
|
+
* Provides loopback proxying on port 28180 (shared across parent and subagents),
|
|
5
5
|
* intelligent routing to OpenCode Zen and KiloCode Gateway, and failover support.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -111,9 +111,8 @@ export async function isProxyAlive(port: number): Promise<boolean> {
|
|
|
111
111
|
|
|
112
112
|
/**
|
|
113
113
|
* Start the local HTTP proxy daemon.
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* parent or sibling OMP session, resolves immediately with { server: null, port: 18080 }.
|
|
114
|
+
* Implements master/worker single-port reuse: if port 28180 is already held by a live
|
|
115
|
+
* parent or sibling OMP session, resolves immediately with { server: null, port: 28180 }.
|
|
117
116
|
*/
|
|
118
117
|
export function startProxy(
|
|
119
118
|
overridePort?: number,
|
package/src/stream-pipe.ts
CHANGED
|
@@ -175,7 +175,8 @@ export function pipeUpstreamStream(
|
|
|
175
175
|
if (!res.headersSent) {
|
|
176
176
|
res.writeHead(502, { "content-type": "application/json" });
|
|
177
177
|
} else {
|
|
178
|
-
|
|
178
|
+
const isSubstantial = totalChunks > 50 && totalBytes > 100 * 1024;
|
|
179
|
+
ensureTerminalEvent(!isSubstantial, errorMsg, true);
|
|
179
180
|
}
|
|
180
181
|
if (!res.writableEnded) {
|
|
181
182
|
res.end();
|