pi-freeflow 1.7.1 → 1.8.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pi-freeflow 🌊
2
2
 
3
- > **25 free models. Up to 1M context. Zero API keys. Infinite scale via your own relay pool.**
3
+ > **28 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
- | **25 Curated Free Models** | 7 OpenCode Zen + 18 KiloCode Gateway models, up to 1M context & 512K output | Ceiling Unlocked | **$0** |
21
+ | **28 Curated Free Models** | 8 OpenCode Zen + 20 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
- ### 25 Curated Models, One Command
35
+ ### 28 Curated Models, One Command
36
36
 
37
37
  ```bash
38
38
  /model → freeflow → pick
@@ -324,7 +324,7 @@ pnpm smoke # verifies extensions/index.ts loads without crashing
324
324
  ```
325
325
  src/
326
326
  ├── index.ts # extension entry, lifecycle hooks
327
- ├── models.ts # 25-model catalog definitions
327
+ ├── models.ts # 28-model catalog definitions
328
328
  ├── catalog.ts # model catalog cache (24h disk)
329
329
  ├── proxy.ts # local proxy server (127.0.0.1:28180)
330
330
  ├── relay.ts # relay selection & round-robin
package/package.json CHANGED
@@ -1,62 +1,62 @@
1
- {
2
- "name": "pi-freeflow",
3
- "type": "module",
4
- "version": "1.7.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
- "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
- "changeset": "changeset",
50
- "docs:dev": "vitepress dev docs",
51
- "docs:build": "vitepress build docs"
52
- },
53
- "devDependencies": {
54
- "@changesets/cli": "^2.27.0",
55
- "@types/node": "^22.13.9",
56
- "typescript": "^5.8.2",
57
- "vitepress": "^1.6.4"
58
- },
59
- "dependencies": {
60
- "undici": "^8.10.0"
61
- }
62
- }
1
+ {
2
+ "name": "pi-freeflow",
3
+ "type": "module",
4
+ "version": "1.8.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
+ "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
+ "changeset": "changeset",
50
+ "docs:dev": "vitepress dev docs",
51
+ "docs:build": "vitepress build docs"
52
+ },
53
+ "devDependencies": {
54
+ "@changesets/cli": "^2.27.0",
55
+ "@types/node": "^22.13.9",
56
+ "typescript": "^5.8.2",
57
+ "vitepress": "^1.6.4"
58
+ },
59
+ "dependencies": {
60
+ "undici": "^8.10.0"
61
+ }
62
+ }
package/src/catalog.ts CHANGED
@@ -34,7 +34,7 @@ import type {
34
34
  export const DEAD_MODEL_IDS = new Set<string>(["deepseek-v4-flash-free", "x-preview-f-free"]);
35
35
  /**
36
36
  * In-memory cache of currently active/available free models.
37
- * Initialized with all 25 verified models for 0ms instant availability.
37
+ * Initialized with all 28 verified models for 0ms instant availability.
38
38
  */
39
39
  let aliveCatalog: RegisteredModel[] = ALL_MODELS.map((m) => ({
40
40
  ...m,
@@ -328,6 +328,6 @@ export async function refreshCatalog(force = false): Promise<RegisteredModel[]>
328
328
  } catch (err) {
329
329
  logDebug("Failed reading stale catalog cache", { error: String(err) });
330
330
  }
331
- // No valid cache — return in-memory static 25 (host will refresh if needed)
331
+ // No valid cache — return in-memory static 28 (host will refresh if needed)
332
332
  return aliveCatalog;
333
333
  }
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 25 free models (7 OpenCode Zen + 18 KiloCode Gateway) with:
4
+ * Provides access to 28 free models (8 OpenCode Zen + 20 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
@@ -114,7 +114,7 @@ export function buildProviderConfig(
114
114
  ): ProviderConfig {
115
115
  return {
116
116
  baseUrl: `http://${HOST}:${port}/v1`,
117
- apiKey: "placeholder",
117
+ apiKey: "public",
118
118
  api: "openai-completions",
119
119
  compat: { supportsDeveloperRole: false },
120
120
  models: models.map((m) => {
@@ -310,7 +310,7 @@ export default async function (pi: ExtensionAPI): Promise<void> {
310
310
  ? `Relay pool ready: ${freshRelayState.relays.length} relay(s). Run /freeflow for pool management.`
311
311
  : "Relay pool empty — direct mode. Run /freeflow deploy to add your own egress.";
312
312
  ctx.ui?.notify?.(
313
- `freeflow ready: 25 free models via local proxy 127.0.0.1:28180. ${hint}`,
313
+ `freeflow ready: 28 free models via local proxy 127.0.0.1:28180. ${hint}`,
314
314
  "info",
315
315
  );
316
316
  }
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 25 verified free models:
5
- * - 7 OpenCode Zen models (1 Responses API + 6 Chat Completions)
6
- * - 18 KiloCode Keyless Gateway models (17 OpenRouter format + 1 Standard format)
4
+ * Defines the 28 verified free models:
5
+ * - 8 OpenCode Zen models (1 Responses API + 7 Chat Completions)
6
+ * - 20 KiloCode Keyless Gateway models (19 OpenRouter format + 1 Standard format)
7
7
  */
8
8
 
9
9
  import type { ModelDef, ThinkingLevelMap, Upstream } from "./types.ts";
@@ -126,6 +126,22 @@ export const OPENCODE_MODELS: ModelDef[] = [
126
126
  xhigh: "xhigh",
127
127
  max: null,},
128
128
  },
129
+ {
130
+ id: "ling-3.0-flash-fin-free",
131
+ name: "Ling 3.0 Flash Fin (256K)",
132
+ reasoning: true,
133
+ contextWindow: 262_144,
134
+ maxTokens: 131_072,
135
+ input: ["text"],
136
+ thinkingLevelMap: {
137
+ off: null,
138
+ minimal: "minimal",
139
+ low: "low",
140
+ medium: "medium",
141
+ high: "high",
142
+ xhigh: "xhigh",
143
+ max: null,},
144
+ },
129
145
  ];
130
146
 
131
147
  /**
@@ -328,6 +344,26 @@ export const KILO_MODELS: ModelDef[] = [
328
344
  thinkingFormat: "openrouter",
329
345
  thinkingLevelMap: KILO_REASONING_MAP,
330
346
  },
347
+ {
348
+ id: "thinkingmachines/inkling:free",
349
+ name: "Inkling (1M)",
350
+ reasoning: true,
351
+ contextWindow: 1_048_576,
352
+ maxTokens: 262_144,
353
+ input: ["text", "image"],
354
+ thinkingFormat: "openrouter",
355
+ thinkingLevelMap: KILO_REASONING_MAP,
356
+ },
357
+ {
358
+ id: "thinkingmachines/inkling-small:free",
359
+ name: "Inkling Small (1M)",
360
+ reasoning: true,
361
+ contextWindow: 1_048_576,
362
+ maxTokens: 262_144,
363
+ input: ["text", "image"],
364
+ thinkingFormat: "openrouter",
365
+ thinkingLevelMap: KILO_REASONING_MAP,
366
+ },
331
367
  ];
332
368
 
333
369
  /**
@@ -352,6 +388,8 @@ export const MODEL_ALIASES: Record<string, string> = {
352
388
  "minimax-m2.7": "minimax/minimax-m2.7:free",
353
389
  "minimax-m3": "minimax/minimax-m3:free",
354
390
  "ling-3.0-flash-fin": "inclusionai/ling-3.0-flash-fin:free",
391
+ "inkling": "thinkingmachines/inkling:free",
392
+ "inkling-small": "thinkingmachines/inkling-small:free",
355
393
  // provider-prefixed short aliases (slash-normalized)
356
394
  "hy3:free": "tencent/hy3:free",
357
395
  "laguna-s-2.1:free": "poolside/laguna-s-2.1:free",
@@ -379,7 +417,7 @@ export const KILO_MODEL_IDS = new Set<string>([
379
417
  ]);
380
418
 
381
419
  /**
382
- * Combined list of all 25 static free models (canonical)
420
+ * Combined list of all 28 static free models (canonical)
383
421
  */
384
422
  export const ALL_MODELS: ModelDef[] = [...OPENCODE_MODELS, ...KILO_MODELS];
385
423
 
package/src/proxy.ts CHANGED
@@ -85,13 +85,12 @@ export function sanitizeHeaders(
85
85
  incoming: http.IncomingHttpHeaders,
86
86
  targetHost: string,
87
87
  ): Record<string, string> {
88
- // Positive allowlist: only headers the proxy is meant to relay. Everything
89
- // else (host, cookie, x-forwarded-*, client x-relay-*) is dropped so a
90
- // browser/extension cannot smuggle headers into the upstream request.
88
+ // authorization is deliberately NOT forwarded: the host provider registers
89
+ // with a dummy key (placeholder), and zen free models are keyless sending
90
+ // that fake key upstream gets 401 Invalid API key. Kilo injects its own key.
91
91
  const allowed: Record<string, true> = {
92
92
  "content-type": true,
93
93
  accept: true,
94
- authorization: true,
95
94
  "x-request-id": true,
96
95
  };
97
96
  const sanitized: Record<string, string> = {};