pi-free 2.1.0 โ†’ 2.1.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/CHANGELOG.md CHANGED
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.1.1] - 2026-06-15
11
+
12
+ ### Fixed
13
+
14
+ - **Cline XML bridge**:
15
+ - Preserve JSON file content as string in `write_to_file` XML โ€” prevents file bodies from being parsed as JSON objects and corrupted ([#244](https://github.com/apmantza/pi-free/pull/244)).
16
+ - Recover heredoc file writes (Model `cat << 'EOF'` pattern in `execute_command`) as `write`/`write_to_file` tool calls ([#246](https://github.com/apmantza/pi-free/pull/246)).
17
+ - Recover XML tool calls from the reasoning stream when MiMo nests tools inside thinking blocks ([#249](https://github.com/apmantza/pi-free/pull/249)).
18
+ - Surface reasoning-only responses: when MiMo puts the entire answer in reasoning with no visible text, surface it as best-effort visible output instead of a blank stop ([#251](https://github.com/apmantza/pi-free/pull/251)).
19
+ - Strip Unicode math-italic XML tag decorations (`<๐‘Ž๐‘›๐‘ก๐‘š๐‘™:thinking>`, `<๐‘Ž๐‘›๐‘ก๐‘š๐‘™:read_file>`) that MiMo emits instead of standard Cline XML tags ([#252](https://github.com/apmantza/pi-free/pull/252)).
20
+ - Hide internal planning phrases and restrict hidden-tool recovery to the reasoning channel only โ€” never leak raw LLM planning as user-visible text ([#252](https://github.com/apmantza/pi-free/pull/252)).
21
+ - Retry MiMo stream errors with reasoning disabled on the second attempt ([#252](https://github.com/apmantza/pi-free/pull/252)).
22
+ - Parse MiMo Pi SDK `<function=name>` tool-call syntax directly โ€” no double conversion through Cline XML ([#255](https://github.com/apmantza/pi-free/pull/255)).
23
+ - Auto-retry reasoning-only MiMo responses with a "continue" nudge instead of showing a dead-end error to the user ([#256](https://github.com/apmantza/pi-free/pull/256)).
24
+
25
+ - **TokenRouter**:
26
+ - Patch nested MiniMax `<think>` blocks that appear inside `reasoning_content` deltas ([#247](https://github.com/apmantza/pi-free/pull/247)).
27
+ - Scope MiniMax thinking patches to active MiniMax models only, avoiding interference with other model families ([#248](https://github.com/apmantza/pi-free/pull/248)).
28
+ - Patch MiniMax payloads in the stream wrapper to prevent malformed SSE from breaking the parser ([#250](https://github.com/apmantza/pi-free/pull/250)).
29
+ - Retry high-load 2064 errors from TokenRouter with automatic backoff ([#254](https://github.com/apmantza/pi-free/pull/254)).
30
+
31
+ - **UI**: Remove provider-count footer status text unconditionally โ€” reduces status bar clutter ([#245](https://github.com/apmantza/pi-free/pull/245)).
32
+
10
33
  ## [2.1.0] - 2026-06-15
11
34
 
12
35
  ### Added
@@ -349,9 +372,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
349
372
  - If ANY model has cost > 0, assumes pricing exposed โ†’ uses Route A
350
373
  - All providers (Cline, Kilo, NVIDIA, Ollama, dynamic built-in) now use this consistent helper
351
374
 
352
- - **CrofAI provider (PAID)** โ€” Added new **paid** provider for CrofAI (https://crof.ai), an OpenAI-compatible LLM inference API. **Note: CrofAI is a paid provider** โ€” users must have a CrofAI API key with credits. The provider uses Route B detection (name-only) since CrofAI's API doesn't expose per-model pricing. Only models with `"free"` in their names are marked as free (none currently).
375
+ - **CrofAI provider (PAID)** โ€” Added new **paid** provider for CrofAI (<https://crof.ai>), an OpenAI-compatible LLM inference API. **Note: CrofAI is a paid provider** โ€” users must have a CrofAI API key with credits. The provider uses Route B detection (name-only) since CrofAI's API doesn't expose per-model pricing. Only models with `"free"` in their names are marked as free (none currently).
353
376
 
354
- - **ZenMux provider (PAID)** โ€” Added new **paid** provider for ZenMux AI gateway (https://zenmux.ai), a unified API for 200+ models from OpenAI, Anthropic, Google, etc. **Note: ZenMux is a paid provider** โ€” users must have a ZenMux API key with credits. The provider uses Route A detection (OR logic) since ZenMux exposes pricing. Models marked as free only if `cost === 0` OR `"free"` in name (2 free models identified: GLM 4.7 Flash Free, GLM 4.6v Flash Free).
377
+ - **ZenMux provider (PAID)** โ€” Added new **paid** provider for ZenMux AI gateway (<https://zenmux.ai>), a unified API for 200+ models from OpenAI, Anthropic, Google, etc. **Note: ZenMux is a paid provider** โ€” users must have a ZenMux API key with credits. The provider uses Route A detection (OR logic) since ZenMux exposes pricing. Models marked as free only if `cost === 0` OR `"free"` in name (2 free models identified: GLM 4.7 Flash Free, GLM 4.6v Flash Free).
355
378
 
356
379
  - **Comprehensive `isFreeModel` test suite** โ€” Added 30+ unit tests covering Route A, Route B, freemium behavior, and edge cases. Tests verify correct classification on actual OpenRouter API data (371 models, 30 free).
357
380
 
@@ -553,7 +576,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
553
576
  - **$0.011 per 1,000 Neurons** beyond free allocation
554
577
  - Only requires `CLOUDFLARE_API_TOKEN` โ€” account ID auto-derived from token
555
578
  - Toggle with `/cloudflare-toggle`
556
- - Create token at https://dash.cloudflare.com/profile/api-tokens
579
+ - Create token at <https://dash.cloudflare.com/profile/api-tokens>
557
580
 
558
581
  - **Unified dynamic built-in providers module** โ€” New `providers/dynamic-built-in/` module that dynamically fetches models from Pi's built-in providers when users have API keys:
559
582
  - **Mistral** (`MISTRAL_API_KEY`) โ€” Fetches from `api.mistral.ai/v1/models`
@@ -95,7 +95,6 @@ export function setupBuiltInProviderToggles(pi: ExtensionAPI): void {
95
95
  for (const config of activeConfigs) {
96
96
  registerToggleCommand(pi, config);
97
97
  }
98
- setupStatusBar(pi, activeConfigs);
99
98
  commandsRegistered = true;
100
99
  }
101
100
 
@@ -250,45 +249,6 @@ function modelToProviderConfig(
250
249
  return base;
251
250
  }
252
251
 
253
- // =============================================================================
254
- // Status bar for provider selection
255
- // =============================================================================
256
-
257
- function setupStatusBar(
258
- pi: ExtensionAPI,
259
- configs: BuiltInToggleConfig[],
260
- ): void {
261
- pi.on("model_select", (_event, ctx) => {
262
- const selected = _event.model?.provider;
263
-
264
- // Clear status for all fallback-captured built-in providers
265
- for (const config of configs) {
266
- if (selected !== config.id) {
267
- ctx.ui.setStatus(`${config.id}-status`, undefined);
268
- }
269
- }
270
-
271
- if (!selected) return;
272
-
273
- const state = providerStates.get(selected);
274
- if (!state) return;
275
-
276
- const free = state.stored.free.length;
277
- const total = state.stored.all.length;
278
- const paid = total - free;
279
- const mode = state.toggleState.getCurrentMode();
280
- let status: string;
281
- if (paid === 0) {
282
- status = `${selected}: ${free} free models`;
283
- } else if (mode === "all") {
284
- status = `${selected}: ${total} models (free + paid)`;
285
- } else {
286
- status = `${selected}: ${free} free \u00b7 ${paid} paid`;
287
- }
288
- ctx.ui.setStatus(`${selected}-status`, status);
289
- });
290
- }
291
-
292
252
  function getApiKeyEnvForProvider(providerId: string): string {
293
253
  const envMap: Record<string, string> = {
294
254
  opencode: "$OPENCODE_API_KEY",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-free",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "type": "module",
5
5
  "description": "AI model providers for Pi with free model filtering and dynamic model fetching",
6
6
  "keywords": [
@@ -222,31 +222,7 @@ export function setupProvider(
222
222
  });
223
223
  }
224
224
 
225
- // โ”€โ”€ Status bar for selected provider โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
226
-
227
- pi.on("model_select", (_event, ctx) => {
228
- if (_event.model?.provider !== providerId) {
229
- ctx.ui.setStatus(`${providerId}-status`, undefined);
230
- return;
231
- }
232
-
233
- // Build status line for this provider
234
- const free = stored.free.length;
235
- const total = stored.all.length || free;
236
- const paid = total - free;
237
- let status: string;
238
-
239
- if (paid === 0) {
240
- status = `${providerId}: ${free} free models`;
241
- } else if (currentShowPaid) {
242
- status = `${providerId}: ${total} models (free + paid)`;
243
- } else {
244
- status = `${providerId}: ${free} free ยท ${paid} paid`;
245
- }
246
-
247
- if (config.hasKey) status += " ๐Ÿ”‘";
248
- ctx.ui.setStatus(`${providerId}-status`, status);
249
- });
225
+ // โ”€โ”€ Model count status bar removed (keeps footer clean) โ”€โ”€โ”€โ”€โ”€โ”€โ”€
250
226
 
251
227
  // โ”€โ”€ Error handling / usage tracking are temporarily deprecated โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
252
228