pi-free 1.0.9 → 2.0.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +138 -0
  2. package/README.md +393 -367
  3. package/config.ts +170 -121
  4. package/constants.ts +23 -61
  5. package/index.ts +148 -0
  6. package/lib/built-in-toggle.ts +206 -0
  7. package/lib/json-persistence.ts +11 -10
  8. package/lib/logger.ts +2 -2
  9. package/lib/model-enhancer.ts +20 -20
  10. package/lib/open-browser.ts +41 -0
  11. package/lib/provider-cache.ts +106 -0
  12. package/lib/registry.ts +144 -0
  13. package/package.json +8 -23
  14. package/provider-factory.ts +25 -41
  15. package/provider-failover/benchmark-lookup.ts +247 -0
  16. package/provider-failover/benchmarks-chunk-0.ts +2010 -0
  17. package/provider-failover/benchmarks-chunk-1.ts +1988 -0
  18. package/provider-failover/benchmarks-chunk-2.ts +2010 -0
  19. package/provider-failover/benchmarks-chunk-3.ts +2010 -0
  20. package/provider-failover/benchmarks-chunk-4.ts +1969 -0
  21. package/provider-failover/hardcoded-benchmarks.ts +22 -10025
  22. package/provider-helper.ts +260 -259
  23. package/providers/{cline-auth.ts → cline/cline-auth.ts} +2 -2
  24. package/providers/cline/cline-models.ts +128 -0
  25. package/providers/{cline.ts → cline/cline.ts} +298 -257
  26. package/providers/cloudflare/cloudflare.ts +368 -0
  27. package/providers/dynamic-built-in/index.ts +432 -0
  28. package/providers/{kilo-auth.ts → kilo/kilo-auth.ts} +3 -20
  29. package/providers/{kilo-models.ts → kilo/kilo-models.ts} +2 -2
  30. package/providers/kilo/kilo.ts +235 -0
  31. package/providers/{modal.ts → modal/modal.ts} +4 -3
  32. package/providers/{nvidia.ts → nvidia/nvidia.ts} +152 -113
  33. package/providers/ollama/ollama.ts +172 -0
  34. package/providers/opencode-session.ts +34 -34
  35. package/providers/{qwen-auth.ts → qwen/qwen-auth.ts} +24 -40
  36. package/providers/{qwen-models.ts → qwen/qwen-models.ts} +101 -95
  37. package/providers/{qwen.ts → qwen/qwen.ts} +83 -13
  38. package/provider-failover/auto-switch.ts +0 -350
  39. package/provider-failover/errors.ts +0 -275
  40. package/provider-failover/index.ts +0 -238
  41. package/providers/cline-models.ts +0 -77
  42. package/providers/factory.ts +0 -125
  43. package/providers/fireworks.ts +0 -49
  44. package/providers/go.ts +0 -216
  45. package/providers/kilo.ts +0 -146
  46. package/providers/mistral.ts +0 -144
  47. package/providers/ollama.ts +0 -113
  48. package/providers/openrouter.ts +0 -175
  49. package/providers/zen.ts +0 -371
  50. package/usage/commands.ts +0 -17
  51. package/usage/cumulative.ts +0 -193
  52. package/usage/formatters.ts +0 -115
  53. package/usage/index.ts +0 -46
  54. package/usage/limits.ts +0 -148
  55. package/usage/metrics.ts +0 -222
  56. package/usage/sessions.ts +0 -355
  57. package/usage/store.ts +0 -99
  58. package/usage/tracking.ts +0 -329
  59. package/usage/types.ts +0 -26
  60. package/usage/widget.ts +0 -90
  61. package/widget/data.ts +0 -113
  62. package/widget/format.ts +0 -26
  63. package/widget/render.ts +0 -117
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Built-in Provider Toggle Support
3
+ *
4
+ * Captures pi's built-in providers after session start and enables
5
+ * free/paid toggling for them via the global registry.
6
+ *
7
+ * Currently supports:
8
+ * - opencode (OpenCode / Zen gateway)
9
+ * - openrouter (OpenRouter)
10
+ *
11
+ * Usage: /toggle-opencode
12
+ */
13
+
14
+ import type { Api, Model } from "@mariozechner/pi-ai";
15
+ import type {
16
+ ExtensionAPI,
17
+ ProviderModelConfig,
18
+ } from "@mariozechner/pi-coding-agent";
19
+ import {
20
+ getOpencodeShowPaid,
21
+ getOpenrouterShowPaid,
22
+ saveConfig,
23
+ } from "../config.ts";
24
+ import { createLogger } from "./logger.ts";
25
+ import {
26
+ getGlobalFreeOnly,
27
+ isFreeModel,
28
+ registerWithGlobalToggle,
29
+ } from "./registry.ts";
30
+
31
+ const _logger = createLogger("built-in-toggle");
32
+
33
+ // =============================================================================
34
+ // Configuration
35
+ // =============================================================================
36
+
37
+ interface BuiltInToggleConfig {
38
+ id: string;
39
+ getShowPaid: () => boolean;
40
+ }
41
+
42
+ const BUILT_IN_TOGGLE_PROVIDERS: BuiltInToggleConfig[] = [
43
+ { id: "opencode", getShowPaid: getOpencodeShowPaid },
44
+ { id: "openrouter", getShowPaid: getOpenrouterShowPaid },
45
+ ];
46
+
47
+ // =============================================================================
48
+ // State
49
+ // =============================================================================
50
+
51
+ interface BuiltInProviderState {
52
+ free: ProviderModelConfig[];
53
+ all: ProviderModelConfig[];
54
+ reRegister: (models: ProviderModelConfig[]) => void;
55
+ showPaid: boolean;
56
+ }
57
+
58
+ const providerStates = new Map<string, BuiltInProviderState>();
59
+ let commandsRegistered = false;
60
+
61
+ // =============================================================================
62
+ // Setup
63
+ // =============================================================================
64
+
65
+ export function setupBuiltInProviderToggles(pi: ExtensionAPI): void {
66
+ // Register toggle commands once (available even before models load)
67
+ if (!commandsRegistered) {
68
+ for (const config of BUILT_IN_TOGGLE_PROVIDERS) {
69
+ registerToggleCommand(pi, config);
70
+ }
71
+ commandsRegistered = true;
72
+ }
73
+
74
+ // Capture built-in models on session start and apply initial filter
75
+ pi.on("session_start", async (_event, ctx) => {
76
+ const available = ctx.modelRegistry.getAvailable();
77
+
78
+ for (const config of BUILT_IN_TOGGLE_PROVIDERS) {
79
+ if (providerStates.has(config.id)) {
80
+ // Already captured this session — skip to avoid re-registering
81
+ continue;
82
+ }
83
+
84
+ const providerModels = available.filter(
85
+ (m: Model<Api>) => m.provider === config.id,
86
+ );
87
+ if (providerModels.length === 0) continue;
88
+
89
+ const allModels = providerModels.map(modelToProviderConfig);
90
+ const freeModels = allModels.filter(isFreeModel);
91
+
92
+ const baseUrl = providerModels[0].baseUrl;
93
+ const api = providerModels[0].api;
94
+ const apiKeyEnv = getApiKeyEnvForProvider(config.id);
95
+
96
+ const reRegister = (models: ProviderModelConfig[]) => {
97
+ pi.registerProvider(config.id, {
98
+ baseUrl,
99
+ apiKey: apiKeyEnv,
100
+ api,
101
+ models,
102
+ });
103
+ };
104
+
105
+ providerStates.set(config.id, {
106
+ free: freeModels,
107
+ all: allModels,
108
+ reRegister,
109
+ showPaid: config.getShowPaid(),
110
+ });
111
+
112
+ // Register with global free-only filter
113
+ registerWithGlobalToggle(
114
+ config.id,
115
+ { free: freeModels, all: allModels },
116
+ reRegister,
117
+ true,
118
+ );
119
+
120
+ _logger.info(
121
+ `[built-in-toggle] ${config.id}: captured ${allModels.length} models (${freeModels.length} free)`,
122
+ );
123
+
124
+ // Respect global free-only setting at capture time
125
+ if (!getGlobalFreeOnly() && !config.getShowPaid()) {
126
+ // Default: show free only (same as other pi-free providers)
127
+ if (freeModels.length > 0) {
128
+ reRegister(freeModels);
129
+ _logger.info(
130
+ `[built-in-toggle] ${config.id}: applied free-only filter`,
131
+ );
132
+ }
133
+ }
134
+ }
135
+ });
136
+ }
137
+
138
+ // =============================================================================
139
+ // Per-provider toggle command
140
+ // =============================================================================
141
+
142
+ function registerToggleCommand(
143
+ pi: ExtensionAPI,
144
+ config: BuiltInToggleConfig,
145
+ ): void {
146
+ const commandName = `toggle-${config.id}`;
147
+ pi.registerCommand(commandName, {
148
+ description: `Toggle free/paid ${config.id} models`,
149
+ handler: async (_args, ctx) => {
150
+ const state = providerStates.get(config.id);
151
+ if (!state) {
152
+ ctx.ui.notify(
153
+ `${config.id}: models not loaded yet. Start a session first.`,
154
+ "warning",
155
+ );
156
+ return;
157
+ }
158
+
159
+ state.showPaid = !state.showPaid;
160
+
161
+ // Persist preference
162
+ saveConfig({ [`${config.id}_show_paid`]: state.showPaid });
163
+
164
+ if (state.showPaid) {
165
+ state.reRegister(state.all);
166
+ ctx.ui.notify(
167
+ `${config.id}: showing all ${state.all.length} models`,
168
+ "info",
169
+ );
170
+ } else {
171
+ state.reRegister(state.free);
172
+ ctx.ui.notify(
173
+ `${config.id}: showing ${state.free.length} free models`,
174
+ "info",
175
+ );
176
+ }
177
+ },
178
+ });
179
+ }
180
+
181
+ // =============================================================================
182
+ // Helpers
183
+ // =============================================================================
184
+
185
+ function modelToProviderConfig(m: Model<Api>): ProviderModelConfig {
186
+ return {
187
+ id: m.id,
188
+ name: m.name,
189
+ api: m.api,
190
+ reasoning: m.reasoning,
191
+ input: m.input,
192
+ cost: m.cost,
193
+ contextWindow: m.contextWindow,
194
+ maxTokens: m.maxTokens,
195
+ headers: m.headers,
196
+ compat: (m as any).compat,
197
+ };
198
+ }
199
+
200
+ function getApiKeyEnvForProvider(providerId: string): string {
201
+ const envMap: Record<string, string> = {
202
+ opencode: "OPENCODE_API_KEY",
203
+ openrouter: "OPENROUTER_API_KEY",
204
+ };
205
+ return envMap[providerId] || `${providerId.toUpperCase()}_API_KEY`;
206
+ }
@@ -5,6 +5,9 @@
5
5
 
6
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
7
  import { dirname } from "node:path";
8
+ import { createLogger } from "./logger.ts";
9
+
10
+ const _logger = createLogger("json-persistence");
8
11
 
9
12
  export interface JSONStore<T> {
10
13
  load(): T;
@@ -28,8 +31,7 @@ export function createJSONStore<T extends object>(
28
31
  return cached;
29
32
  }
30
33
  } catch (err) {
31
- // Silently fail and return default
32
- void err;
34
+ _logger.warn("Failed to load JSON store, using default", { filepath, error: err });
33
35
  }
34
36
  cached = defaultValue;
35
37
  return cached;
@@ -44,8 +46,7 @@ export function createJSONStore<T extends object>(
44
46
  }
45
47
  writeFileSync(filepath, `${JSON.stringify(data, null, 2)}\n`, "utf-8");
46
48
  } catch (err) {
47
- // Silently fail - persistence is best-effort
48
- void err;
49
+ _logger.warn("Failed to save JSON store", { filepath, error: err });
49
50
  }
50
51
  }
51
52
 
@@ -71,8 +72,8 @@ export function createJSONLStore<T extends object>(
71
72
  .filter((line) => line.trim())
72
73
  .map((line) => JSON.parse(line) as T);
73
74
  }
74
- } catch {
75
- // Return empty on error
75
+ } catch (err) {
76
+ _logger.warn("Failed to load JSONL store, using empty array", { filepath, error: err });
76
77
  }
77
78
  return [];
78
79
  }
@@ -85,16 +86,16 @@ export function createJSONLStore<T extends object>(
85
86
  }
86
87
  const line = JSON.stringify(entry);
87
88
  writeFileSync(filepath, `${line}\n`, { flag: "a", encoding: "utf-8" });
88
- } catch {
89
- // Silently fail
89
+ } catch (err) {
90
+ _logger.warn("Failed to append to JSONL store", { filepath, error: err });
90
91
  }
91
92
  }
92
93
 
93
94
  function clear(): void {
94
95
  try {
95
96
  writeFileSync(filepath, "", "utf-8");
96
- } catch {
97
- // Silently fail
97
+ } catch (err) {
98
+ _logger.warn("Failed to clear JSONL store", { filepath, error: err });
98
99
  }
99
100
  }
100
101
 
package/lib/logger.ts CHANGED
@@ -63,8 +63,8 @@ function appendToFile(line: string): void {
63
63
  mkdirSync(dir, { recursive: true });
64
64
  }
65
65
  appendFileSync(LOG_PATH, `${line}\n`, "utf8");
66
- } catch {
67
- // Never throw from logger
66
+ } catch (err) {
67
+ console.error("Failed to write to log file:", err);
68
68
  }
69
69
  }
70
70
 
@@ -1,20 +1,20 @@
1
- /**
2
- * Model name enhancement helper
3
- * Adds Coding Index scores to model names for display in /model
4
- */
5
-
6
- import type { ProviderModelConfig } from "@mariozechner/pi-coding-agent";
7
- import { enhanceModelNameWithCodingIndex } from "../provider-failover/hardcoded-benchmarks.ts";
8
-
9
- /**
10
- * Enhance model names with Coding Index scores
11
- * Use this before registering providers to show CI in /model list
12
- */
13
- export function enhanceModelsWithCodingIndex(
14
- models: ProviderModelConfig[],
15
- ): ProviderModelConfig[] {
16
- return models.map((m) => ({
17
- ...m,
18
- name: enhanceModelNameWithCodingIndex(m.name, m.id),
19
- }));
20
- }
1
+ /**
2
+ * Model name enhancement helper
3
+ * Adds Coding Index scores to model names for display in /model
4
+ */
5
+
6
+ import type { ProviderModelConfig } from "@mariozechner/pi-coding-agent";
7
+ import { enhanceModelNameWithCodingIndex } from "../provider-failover/benchmark-lookup.ts";
8
+
9
+ /**
10
+ * Enhance model names with Coding Index scores
11
+ * Use this before registering providers to show CI in /model list
12
+ */
13
+ export function enhanceModelsWithCodingIndex(
14
+ models: ProviderModelConfig[],
15
+ ): ProviderModelConfig[] {
16
+ return models.map((m) => ({
17
+ ...m,
18
+ name: enhanceModelNameWithCodingIndex(m.name, m.id),
19
+ }));
20
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Cross-platform browser opener
3
+ *
4
+ * Opens a URL in the user's default browser. Handles URL-unsafe characters
5
+ * on Windows by using PowerShell's Start-Process instead of cmd.exe.
6
+ */
7
+
8
+ import { spawn } from "node:child_process";
9
+
10
+ /**
11
+ * Open a URL in the user's default browser.
12
+ *
13
+ * - Windows: uses PowerShell Start-Process (cmd.exe interprets & as command separator)
14
+ * - macOS: uses `open`
15
+ * - Linux/BSD: uses `xdg-open`
16
+ */
17
+ export function openBrowser(url: string): void {
18
+ try {
19
+ if (process.platform === "win32") {
20
+ // PowerShell's Start-Process treats the URL as a literal string,
21
+ // unlike cmd.exe which interprets & as a command separator.
22
+ spawn(
23
+ "powershell.exe",
24
+ [
25
+ "-NoProfile",
26
+ "-NonInteractive",
27
+ "-Command",
28
+ `Start-Process "${url.replace(/"/g, '\\"')}"`,
29
+ ],
30
+ { detached: true, shell: false, windowsHide: true },
31
+ ).unref();
32
+ } else if (process.platform === "darwin") {
33
+ spawn("open", [url], { detached: true }).unref();
34
+ } else {
35
+ spawn("xdg-open", [url], { detached: true }).unref();
36
+ }
37
+ } catch (err) {
38
+ // Best-effort — browser opening is non-critical
39
+ console.debug("Failed to open browser:", err);
40
+ }
41
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Provider Model Cache
3
+ *
4
+ * Caches provider model lists to disk for faster startup and offline use.
5
+ *
6
+ * Flow:
7
+ * 1. On session_start: fetch fresh models from API, save to cache
8
+ * 2. On extension load: register cached models immediately (shows in --list-models)
9
+ * 3. If API fails: use cached models as fallback
10
+ */
11
+
12
+ import { homedir } from "node:os";
13
+ import { join } from "node:path";
14
+ import { createJSONStore } from "./json-persistence.ts";
15
+ import { createLogger } from "./logger.ts";
16
+ import type { ProviderModelConfig } from "./types.ts";
17
+
18
+ const _logger = createLogger("provider-cache");
19
+
20
+ // =============================================================================
21
+ // Types
22
+ // =============================================================================
23
+
24
+ export interface CachedProviderModels {
25
+ /** Provider ID */
26
+ provider: string;
27
+ /** Cached model list */
28
+ models: ProviderModelConfig[];
29
+ /** When these models were fetched */
30
+ fetchedAt: string; // ISO timestamp
31
+ }
32
+
33
+ interface CacheData {
34
+ providers: Record<string, CachedProviderModels>;
35
+ }
36
+
37
+ // =============================================================================
38
+ // Cache Store
39
+ // =============================================================================
40
+
41
+ const CACHE_FILE = join(homedir(), ".pi", "provider-cache.json");
42
+
43
+ const _cache = createJSONStore<CacheData>(CACHE_FILE, { providers: {} });
44
+
45
+ /**
46
+ * Load cached models for a provider.
47
+ * Returns undefined if no cache exists.
48
+ */
49
+ export function loadProviderCache(
50
+ providerId: string,
51
+ ): ProviderModelConfig[] | undefined {
52
+ const data = _cache.load();
53
+ const cached = data.providers[providerId];
54
+
55
+ if (!cached) {
56
+ return undefined;
57
+ }
58
+
59
+ _logger.debug(`Loaded cached models for ${providerId}`, {
60
+ count: cached.models.length,
61
+ fetchedAt: cached.fetchedAt,
62
+ });
63
+
64
+ return cached.models;
65
+ }
66
+
67
+ /**
68
+ * Save models to cache for a provider.
69
+ */
70
+ export function saveProviderCache(
71
+ providerId: string,
72
+ models: ProviderModelConfig[],
73
+ ): void {
74
+ const data = _cache.load();
75
+
76
+ data.providers[providerId] = {
77
+ provider: providerId,
78
+ models,
79
+ fetchedAt: new Date().toISOString(),
80
+ };
81
+
82
+ _cache.save(data);
83
+
84
+ _logger.debug(`Saved ${models.length} models to cache for ${providerId}`);
85
+ }
86
+
87
+ /**
88
+ * Clear cached models for a provider.
89
+ */
90
+ export function clearProviderCache(providerId: string): void {
91
+ const data = _cache.load();
92
+
93
+ if (data.providers[providerId]) {
94
+ delete data.providers[providerId];
95
+ _cache.save(data);
96
+ _logger.debug(`Cleared cache for ${providerId}`);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Clear all provider caches.
102
+ */
103
+ export function clearAllProviderCaches(): void {
104
+ _cache.save({ providers: {} });
105
+ _logger.debug("Cleared all provider caches");
106
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Global Provider Registry for pi-free.
3
+ *
4
+ * Decoupled from index.ts so providers can import toggle logic
5
+ * without creating a circular dependency.
6
+ */
7
+
8
+ import type {
9
+ ExtensionAPI,
10
+ ProviderModelConfig,
11
+ } from "@mariozechner/pi-coding-agent";
12
+ import { getFreeOnly, saveConfig } from "../config.ts";
13
+ import { createLogger } from "./logger.ts";
14
+
15
+ const _logger = createLogger("pi-free");
16
+
17
+ // =============================================================================
18
+ // Types
19
+ // =============================================================================
20
+
21
+ interface ProviderEntry {
22
+ id: string;
23
+ stored: { free: ProviderModelConfig[]; all: ProviderModelConfig[] };
24
+ reRegister: (models: ProviderModelConfig[]) => void;
25
+ hasKey: boolean;
26
+ }
27
+
28
+ // =============================================================================
29
+ // State
30
+ // =============================================================================
31
+
32
+ const providerRegistry = new Map<string, ProviderEntry>();
33
+ let globalFreeOnly = getFreeOnly();
34
+
35
+ // Providers that expose actual per-model pricing via API
36
+ const PRICING_EXPOSED_PROVIDERS = new Set([
37
+ "openrouter",
38
+ "opencode",
39
+ "kilo",
40
+ "cline",
41
+ ]);
42
+
43
+ // =============================================================================
44
+ // Free-model detection
45
+ // =============================================================================
46
+
47
+ /**
48
+ * Check if a model is free.
49
+ *
50
+ * For providers with pricing APIs: uses cost (input === 0 && output === 0)
51
+ * For providers without pricing: ONLY uses name-based check (name includes "free")
52
+ */
53
+ export function isFreeModel(
54
+ model: ProviderModelConfig & { provider?: string },
55
+ ): boolean {
56
+ const provider = model.provider;
57
+ const hasPricing = provider && PRICING_EXPOSED_PROVIDERS.has(provider);
58
+
59
+ // For providers WITH pricing API: cost-based check
60
+ if (hasPricing) {
61
+ if ((model.cost?.input ?? 0) === 0 && (model.cost?.output ?? 0) === 0) {
62
+ return true;
63
+ }
64
+ }
65
+
66
+ // For providers WITHOUT pricing API: ONLY name-based check
67
+ if (model.name.toLowerCase().includes("free")) {
68
+ return true;
69
+ }
70
+
71
+ return false;
72
+ }
73
+
74
+ // =============================================================================
75
+ // Registration
76
+ // =============================================================================
77
+
78
+ /** Register a provider with the global free/paid toggle system */
79
+ export function registerWithGlobalToggle(
80
+ providerId: string,
81
+ stored: { free: ProviderModelConfig[]; all: ProviderModelConfig[] },
82
+ reRegister: (models: ProviderModelConfig[]) => void,
83
+ hasKey: boolean = false,
84
+ ): void {
85
+ providerRegistry.set(providerId, {
86
+ id: providerId,
87
+ stored,
88
+ reRegister,
89
+ hasKey,
90
+ });
91
+ _logger.info(
92
+ `[pi-free] Registered ${providerId} with global toggle (${stored.free.length} free, ${stored.all.length} total)`,
93
+ );
94
+ }
95
+
96
+ /** Get current global free-only state */
97
+ export function getGlobalFreeOnly(): boolean {
98
+ return globalFreeOnly;
99
+ }
100
+
101
+ /** Access the raw registry (used by /free-providers command) */
102
+ export function getProviderRegistry(): ReadonlyMap<string, ProviderEntry> {
103
+ return providerRegistry;
104
+ }
105
+
106
+ // =============================================================================
107
+ // Global filter application
108
+ // =============================================================================
109
+
110
+ export function applyGlobalFilter(_pi: ExtensionAPI, freeOnly: boolean): void {
111
+ globalFreeOnly = freeOnly;
112
+ saveConfig({ free_only: freeOnly });
113
+
114
+ for (const [providerId, entry] of providerRegistry) {
115
+ try {
116
+ if (freeOnly) {
117
+ // Show only free models
118
+ if (entry.stored.free.length > 0) {
119
+ entry.reRegister(entry.stored.free);
120
+ _logger.info(
121
+ `[pi-free] ${providerId}: filtered to ${entry.stored.free.length} free models`,
122
+ );
123
+ } else {
124
+ _logger.warn(`[pi-free] ${providerId}: no free models available`);
125
+ }
126
+ } else {
127
+ // Show all models (paid + free)
128
+ const allModels =
129
+ entry.stored.all.length > 0 ? entry.stored.all : entry.stored.free;
130
+ if (allModels.length > 0) {
131
+ entry.reRegister(allModels);
132
+ _logger.info(
133
+ `[pi-free] ${providerId}: showing all ${allModels.length} models`,
134
+ );
135
+ }
136
+ }
137
+ } catch (err) {
138
+ _logger.error(
139
+ `[pi-free] Failed to apply filter to ${providerId}`,
140
+ err instanceof Error ? { error: err.message } : { error: String(err) },
141
+ );
142
+ }
143
+ }
144
+ }
package/package.json CHANGED
@@ -1,22 +1,19 @@
1
1
  {
2
2
  "name": "pi-free",
3
- "version": "1.0.9",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
- "description": "AIO Free AI models for Pi - Access free models from Kilo, Zen, OpenRouter, NVIDIA, Cline, Mistral, Ollama, and Qwen",
5
+ "description": "AIO free models for PI: Kilo, Cline, Nvidia, Ollama Cloud and others",
6
6
  "keywords": [
7
7
  "pi-package",
8
8
  "pi-extension",
9
9
  "free-models",
10
- "ai-providers",
11
- "openrouter",
10
+ "model-filter",
12
11
  "nvidia-nim",
13
12
  "kilo",
14
13
  "cline",
15
- "ollama",
16
- "mistral",
17
- "fireworks",
18
14
  "qwen",
19
- "qwen-oauth"
15
+ "qwen-oauth",
16
+ "modal"
20
17
  ],
21
18
  "license": "MIT",
22
19
  "author": "Apostolos Mantzaris",
@@ -32,11 +29,10 @@
32
29
  "node": ">=20.0.0"
33
30
  },
34
31
  "files": [
32
+ "index.ts",
35
33
  "providers/**/*.ts",
36
34
  "lib/**/*.ts",
37
- "usage/**/*.ts",
38
35
  "provider-failover/**/*.ts",
39
- "widget/**/*.ts",
40
36
  "config.ts",
41
37
  "constants.ts",
42
38
  "provider-factory.ts",
@@ -55,8 +51,7 @@
55
51
  "peerDependencies": {
56
52
  "@mariozechner/pi-ai": "*",
57
53
  "@mariozechner/pi-coding-agent": "*",
58
- "@mariozechner/pi-tui": "*",
59
- "@sinclair/typebox": "*"
54
+ "@mariozechner/pi-tui": "*"
60
55
  },
61
56
  "devDependencies": {
62
57
  "@vitest/ui": "^1.0.0",
@@ -66,17 +61,7 @@
66
61
  },
67
62
  "pi": {
68
63
  "extensions": [
69
- "./providers/kilo.ts",
70
- "./providers/zen.ts",
71
- "./providers/go.ts",
72
- "./providers/openrouter.ts",
73
- "./providers/nvidia.ts",
74
- "./providers/cline.ts",
75
- "./providers/fireworks.ts",
76
- "./providers/mistral.ts",
77
- "./providers/ollama.ts",
78
- "./providers/qwen.ts",
79
- "./providers/modal.ts"
64
+ "./index.ts"
80
65
  ]
81
66
  }
82
67
  }