opencode-pollinations-plugin 5.1.16 → 5.1.18

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
@@ -4,7 +4,7 @@ import { execSync } from 'child_process';
4
4
  import { generatePollinationsConfig } from './server/generate-config.js';
5
5
  import { loadConfig } from './server/config.js';
6
6
  import { handleChatCompletion } from './server/proxy.js';
7
- import { createToastHooks, setGlobalClient } from './server/toast.js';
7
+ import { createToastHooks, setGlobalClient, emitStatusToast } from './server/toast.js';
8
8
  import { createStatusHooks } from './server/status.js';
9
9
  import { createCommandHooks } from './server/commands.js';
10
10
  const LIFE_LOG = '/tmp/POLLI_LIFECYCLE.log';
@@ -27,11 +27,14 @@ try {
27
27
  log(`[Init] Checking port ${TRACKING_PORT} for zombies...`);
28
28
  execSync(`fuser -k ${TRACKING_PORT}/tcp || true`);
29
29
  log(`[Init] Port ${TRACKING_PORT} cleaned.`);
30
+ execSync('sleep 1');
30
31
  }
31
32
  catch (e) {
32
33
  log(`[Init] Zombie cleanup warning: ${e}`);
33
34
  }
34
35
  // === GESTION DU CYCLE DE VIE PROXY ===
36
+ // CONFIG WATCHER (Hot Reload)
37
+ // CONFIG WATCHER REMOVED (Legacy)
35
38
  const startProxy = () => {
36
39
  return new Promise((resolve) => {
37
40
  const server = http.createServer(async (req, res) => {
@@ -49,13 +52,29 @@ const startProxy = () => {
49
52
  res.writeHead(200, { 'Content-Type': 'application/json' });
50
53
  res.end(JSON.stringify({
51
54
  status: "ok",
52
- version: "v4.0.5",
53
- mode: config.mode
55
+ version: "v5.1.17",
56
+ mode: config.mode,
57
+ pid: process.pid
54
58
  }));
55
59
  return;
56
60
  }
61
+ // RESTORED: Models Endpoint
62
+ if (req.method === 'GET' && req.url === '/v1/models') {
63
+ try {
64
+ const { getAggregatedModels } = await import('./server/pollinations-api.js');
65
+ const models = await getAggregatedModels();
66
+ res.writeHead(200, { 'Content-Type': 'application/json' });
67
+ res.end(JSON.stringify(models));
68
+ log(`[Proxy] Served ${models.data?.length || 0} models`);
69
+ }
70
+ catch (e) {
71
+ log(`[Proxy] Error fetching models: ${e}`);
72
+ res.writeHead(500);
73
+ res.end(JSON.stringify({ error: String(e) }));
74
+ }
75
+ return;
76
+ }
57
77
  // SUPPORT FLEXIBLE DES PATHS
58
- // Le SDK peut envoyer /v1/chat/completions ou juste /chat/completions
59
78
  if (req.method === 'POST' && (req.url === '/v1/chat/completions' || req.url === '/chat/completions')) {
60
79
  const chunks = [];
61
80
  req.on('data', chunk => chunks.push(chunk));
@@ -63,9 +82,10 @@ const startProxy = () => {
63
82
  try {
64
83
  const bodyRaw = Buffer.concat(chunks).toString();
65
84
  await handleChatCompletion(req, res, bodyRaw);
85
+ log(`[Proxy] Chat Completion Success`);
66
86
  }
67
87
  catch (e) {
68
- log(`Error: ${e}`);
88
+ log(`[Proxy] Chat Error: ${e}`);
69
89
  if (!res.headersSent) {
70
90
  res.writeHead(500);
71
91
  res.end(JSON.stringify({ error: String(e) }));
@@ -79,11 +99,12 @@ const startProxy = () => {
79
99
  res.end("Not Found");
80
100
  });
81
101
  server.listen(TRACKING_PORT, '127.0.0.1', () => {
82
- log(`[Proxy] Started V4 on port ${TRACKING_PORT}`);
102
+ log(`[Proxy] Started V5.1.17 on port ${TRACKING_PORT}`);
83
103
  resolve(TRACKING_PORT);
84
104
  });
85
105
  server.on('error', (e) => {
86
106
  log(`[Proxy] Fatal Error: ${e}`);
107
+ // Retry logic could go here, but for now log is key
87
108
  resolve(0);
88
109
  });
89
110
  });
@@ -107,7 +128,12 @@ export const PollinationsPlugin = async (ctx) => {
107
128
  return {
108
129
  async config(config) {
109
130
  log("[Hook] config() called");
110
- const modelsArray = await generatePollinationsConfig();
131
+ // Extract API Key from incoming config to ensure Hot Reload
132
+ const incomingKey = config.provider?.pollinations?.options?.apiKey ||
133
+ config.provider?.pollinations_enter?.options?.apiKey;
134
+ if (incomingKey)
135
+ log(`[Hook] Detected API Key update.`);
136
+ const modelsArray = await generatePollinationsConfig(incomingKey);
111
137
  const modelsObj = {};
112
138
  for (const m of modelsArray) {
113
139
  // Ensure ID is relative for mapping ("free/gemini")
@@ -126,6 +152,7 @@ export const PollinationsPlugin = async (ctx) => {
126
152
  models: modelsObj
127
153
  };
128
154
  log(`[Hook] Registered ${Object.keys(modelsObj).length} models.`);
155
+ emitStatusToast('info', `${Object.keys(modelsObj).length} Models Loaded`, 'Pollinations');
129
156
  },
130
157
  ...toastHooks,
131
158
  ...createStatusHooks(ctx.client), // New Status Bar Logic
@@ -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,12 @@ function formatName(id, censored = true) {
48
48
  return clean;
49
49
  }
50
50
  // --- MAIN GENERATOR logic ---
51
- export async function generatePollinationsConfig() {
51
+ export async function generatePollinationsConfig(forceApiKey) {
52
52
  const config = loadConfig();
53
53
  const modelsOutput = [];
54
- log(`Starting Configuration (V4.5 Clean Dynamic)...`);
54
+ // Use forced key (from Hook) or cached key
55
+ const effectiveKey = forceApiKey || config.apiKey;
56
+ log(`Starting Configuration (V5.1.18 Hot-Reload)...`);
55
57
  // 1. FREE UNIVERSE
56
58
  try {
57
59
  // Switch to main models endpoint (User provided curl confirms it has 'description')
@@ -71,10 +73,10 @@ export async function generatePollinationsConfig() {
71
73
  modelsOutput.push({ id: "free/gemini", name: "[Free] Gemini Flash (Fallback)", object: "model", variants: {} });
72
74
  }
73
75
  // 2. ENTERPRISE UNIVERSE
74
- if (config.apiKey && config.apiKey.length > 5 && config.apiKey !== 'dummy') {
76
+ if (effectiveKey && effectiveKey.length > 5 && effectiveKey !== 'dummy') {
75
77
  try {
76
78
  const enterListRaw = await fetchJson('https://gen.pollinations.ai/text/models', {
77
- 'Authorization': `Bearer ${config.apiKey}`
79
+ 'Authorization': `Bearer ${effectiveKey}`
78
80
  });
79
81
  const enterList = Array.isArray(enterListRaw) ? enterListRaw : (enterListRaw.data || []);
80
82
  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.16",
4
+ "version": "5.1.18",
5
5
  "description": "Native Pollinations.ai Provider Plugin for OpenCode",
6
6
  "publisher": "pollinations",
7
7
  "repository": {