opencode-pollinations-plugin 5.1.21 → 5.1.23

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/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import * as http from 'http';
2
2
  import * as fs from 'fs';
3
3
  import { execSync } from 'child_process';
4
4
  import { generatePollinationsConfig } from './server/generate-config.js';
5
- import { loadConfig } from './server/config.js';
5
+ import { loadConfig, updateCache } from './server/config.js';
6
6
  import { handleChatCompletion } from './server/proxy.js';
7
7
  import { createToastHooks, setGlobalClient } from './server/toast.js';
8
8
  import { createStatusHooks } from './server/status.js';
@@ -100,7 +100,14 @@ export const PollinationsPlugin = async (ctx) => {
100
100
  return {
101
101
  async config(config) {
102
102
  log("[Hook] config() called");
103
- const modelsArray = await generatePollinationsConfig();
103
+ // Extract API Key from incoming config to ensure Hot Reload
104
+ const incomingKey = config.provider?.pollinations?.options?.apiKey ||
105
+ config.provider?.pollinations_enter?.options?.apiKey;
106
+ if (incomingKey) {
107
+ log(`[Hook] Detected API Key update.`);
108
+ updateCache({ apiKey: incomingKey, mode: 'pro' });
109
+ }
110
+ const modelsArray = await generatePollinationsConfig(incomingKey);
104
111
  const modelsObj = {};
105
112
  for (const m of modelsArray) {
106
113
  // Ensure ID is relative for mapping ("free/gemini")
@@ -21,9 +21,11 @@ export interface PollinationsConfigV5 {
21
21
  };
22
22
  enablePaidTools: boolean;
23
23
  statusBar: boolean;
24
+ _loadedAt?: number;
24
25
  }
25
26
  export declare function subscribeToConfigChange(callback: () => void): void;
26
27
  export declare function loadConfig(): PollinationsConfigV5;
28
+ export declare function updateCache(newConfig: Partial<PollinationsConfigV5>): void;
27
29
  export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
28
30
  version: string;
29
31
  mode: "manual" | "alwaysfree" | "pro";
@@ -47,4 +49,5 @@ export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
47
49
  };
48
50
  enablePaidTools: boolean;
49
51
  statusBar: boolean;
52
+ _loadedAt?: number;
50
53
  };
@@ -98,8 +98,27 @@ export function loadConfig() {
98
98
  watchFileSafe(CONFIG_FILE);
99
99
  watchFileSafe(AUTH_FILE);
100
100
  watchFileSafe(OPENCODE_CONFIG_FILE);
101
+ // SMART CACHE: Check mtime to ensure freshness (Hot Reload Fix)
102
+ try {
103
+ if (fs.existsSync(AUTH_FILE)) {
104
+ const stats = fs.statSync(AUTH_FILE);
105
+ // If cache is null or file is newer than our last load
106
+ if (!cachedConfig || !cachedConfig._loadedAt || stats.mtimeMs > cachedConfig._loadedAt) {
107
+ logConfig(`[SmartCache] Auth file changed (mtime). Reloading...`);
108
+ cachedConfig = readConfigFromDisk();
109
+ }
110
+ }
111
+ }
112
+ catch (e) {
113
+ logConfig(`[SmartCache] Error checking mtime: ${e}`);
114
+ }
101
115
  return cachedConfig;
102
116
  }
117
+ export function updateCache(newConfig) {
118
+ const current = loadConfig();
119
+ cachedConfig = { ...current, ...newConfig, _loadedAt: Date.now() }; // Update timestamp
120
+ logConfig(`Cache Force-Updated via Hook. Mode: ${cachedConfig.mode}`);
121
+ }
103
122
  // INTERNAL READER (The old loadConfig logic)
104
123
  function readConfigFromDisk() {
105
124
  let config = { ...DEFAULT_CONFIG_V5 };
@@ -172,7 +191,7 @@ function readConfigFromDisk() {
172
191
  if (!keyFound && config.mode === 'pro') {
173
192
  config.mode = 'manual';
174
193
  }
175
- return { ...config, version: PKG_VERSION };
194
+ return { ...config, version: PKG_VERSION, _loadedAt: Date.now() };
176
195
  }
177
196
  export function saveConfig(updates) {
178
197
  try {
@@ -9,5 +9,5 @@ interface OpenCodeModel {
9
9
  output?: number;
10
10
  };
11
11
  }
12
- export declare function generatePollinationsConfig(): Promise<OpenCodeModel[]>;
12
+ export declare function generatePollinationsConfig(forceApiKey?: string): Promise<OpenCodeModel[]>;
13
13
  export {};
@@ -48,10 +48,13 @@ function formatName(id, censored = true) {
48
48
  return clean;
49
49
  }
50
50
  // --- MAIN GENERATOR logic ---
51
- export async function generatePollinationsConfig() {
51
+ // --- MAIN GENERATOR logic ---
52
+ export async function generatePollinationsConfig(forceApiKey) {
52
53
  const config = loadConfig();
53
54
  const modelsOutput = [];
54
- log(`Starting Configuration (V4.5 Clean Dynamic)...`);
55
+ log(`Starting Configuration (V5.1.22 Hot-Reload)...`);
56
+ // Use forced key (from Hook) or cached key
57
+ const effectiveKey = forceApiKey || config.apiKey;
55
58
  // 1. FREE UNIVERSE
56
59
  try {
57
60
  // Switch to main models endpoint (User provided curl confirms it has 'description')
@@ -71,10 +74,10 @@ export async function generatePollinationsConfig() {
71
74
  modelsOutput.push({ id: "free/gemini", name: "[Free] Gemini Flash (Fallback)", object: "model", variants: {} });
72
75
  }
73
76
  // 2. ENTERPRISE UNIVERSE
74
- if (config.apiKey && config.apiKey.length > 5 && config.apiKey !== 'dummy') {
77
+ if (effectiveKey && effectiveKey.length > 5 && effectiveKey !== 'dummy') {
75
78
  try {
76
79
  const enterListRaw = await fetchJson('https://gen.pollinations.ai/text/models', {
77
- 'Authorization': `Bearer ${config.apiKey}`
80
+ 'Authorization': `Bearer ${effectiveKey}`
78
81
  });
79
82
  const enterList = Array.isArray(enterListRaw) ? enterListRaw : (enterListRaw.data || []);
80
83
  enterList.forEach((m) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opencode-pollinations-plugin",
3
3
  "displayName": "Pollinations AI (V5.1)",
4
- "version": "5.1.21",
4
+ "version": "5.1.23",
5
5
  "description": "Native Pollinations.ai Provider Plugin for OpenCode",
6
6
  "publisher": "pollinations",
7
7
  "repository": {