opencode-pollinations-plugin 5.8.4-beta.1 → 5.8.4-beta.10

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
@@ -100,11 +100,13 @@ export const PollinationsPlugin = async (ctx) => {
100
100
  const version = require('../package.json').version;
101
101
  config.provider['pollinations'] = {
102
102
  id: 'pollinations',
103
+ npm: require('../package.json').name,
103
104
  name: `Pollinations AI (v${version})`,
104
105
  options: { baseURL: localBaseUrl },
105
106
  models: modelsObj
106
107
  };
107
108
  log(`[Hook] Registered ${Object.keys(modelsObj).length} models.`);
109
+ log(`[Hook] Keys: ${Object.keys(modelsObj).join(', ')}`);
108
110
  },
109
111
  ...toastHooks,
110
112
  ...createStatusHooks(ctx.client),
@@ -1,8 +1,6 @@
1
1
  interface OpenCodeModel {
2
2
  id: string;
3
3
  name: string;
4
- object: string;
5
- variants?: any;
6
4
  options?: any;
7
5
  limit?: {
8
6
  context?: number;
@@ -12,6 +10,7 @@ interface OpenCodeModel {
12
10
  input?: string[];
13
11
  output?: string[];
14
12
  };
13
+ tool_call?: boolean;
15
14
  }
16
15
  export declare function generatePollinationsConfig(forceApiKey?: string, forceStrict?: boolean): Promise<OpenCodeModel[]>;
17
16
  export {};
@@ -7,15 +7,8 @@ const HOMEDIR = os.homedir();
7
7
  const CONFIG_DIR_POLLI = path.join(HOMEDIR, '.pollinations');
8
8
  const CACHE_FILE = path.join(CONFIG_DIR_POLLI, 'models-cache.json');
9
9
  // --- CONSTANTS ---
10
- // Seed from _archs/debug_free.json
11
- const DEFAULT_FREE_MODELS = [
12
- { "name": "gemini", "description": "Gemini 2.5 Flash Lite", "tier": "anonymous", "tools": true, "input_modalities": ["text", "image"], "output_modalities": ["text"], "vision": true },
13
- { "name": "mistral", "description": "Mistral Small 3.2 24B", "tier": "anonymous", "tools": true, "input_modalities": ["text"], "output_modalities": ["text"], "vision": false },
14
- { "name": "openai-fast", "description": "GPT-OSS 20B Reasoning LLM (OVH)", "tier": "anonymous", "tools": true, "input_modalities": ["text"], "output_modalities": ["text"], "vision": false, "reasoning": true },
15
- { "name": "bidara", "description": "BIDARA (Biomimetic Designer)", "tier": "anonymous", "community": true, "input_modalities": ["text", "image"], "output_modalities": ["text"], "vision": true },
16
- { "name": "chickytutor", "description": "ChickyTutor AI Language Tutor", "tier": "anonymous", "community": true, "input_modalities": ["text"], "output_modalities": ["text"] },
17
- { "name": "midijourney", "description": "MIDIjourney", "tier": "anonymous", "community": true, "input_modalities": ["text"], "output_modalities": ["text"] }
18
- ];
10
+ // Seed from models-seed.ts
11
+ import { FREE_MODELS_SEED } from './models-seed.js';
19
12
  // --- LOGGING ---
20
13
  const LOG_FILE = '/tmp/opencode_pollinations_config.log';
21
14
  function log(msg) {
@@ -105,7 +98,7 @@ function saveCache(models, etag) {
105
98
  export async function generatePollinationsConfig(forceApiKey, forceStrict = false) {
106
99
  const config = loadConfig();
107
100
  const modelsOutput = [];
108
- log(`Starting Configuration (v5.8.4-Beta1)...`);
101
+ log(`Starting Configuration (v5.8.4-Debug-Tools)...`);
109
102
  const effectiveKey = forceApiKey || config.apiKey;
110
103
  // 1. FREE UNIVERSE (Smart Cache System)
111
104
  let freeModelsList = [];
@@ -157,7 +150,7 @@ export async function generatePollinationsConfig(forceApiKey, forceStrict = fals
157
150
  }
158
151
  else {
159
152
  log('Using DEFAULT SEED models (Offline + No Cache).');
160
- freeModelsList = DEFAULT_FREE_MODELS;
153
+ freeModelsList = FREE_MODELS_SEED;
161
154
  }
162
155
  }
163
156
  }
@@ -170,7 +163,7 @@ export async function generatePollinationsConfig(forceApiKey, forceStrict = fals
170
163
  // Tag (Offline) only if we explicitly failed a fetch attempt or are using Fallback SEED when fetch failed.
171
164
  // If we use cache because it's valid (Skipped fetch), we don't tag (Offline).
172
165
  const suffix = isOffline ? ' (Offline)' : '';
173
- const mapped = mapModel(m, 'free/', `[Free] `, suffix);
166
+ const mapped = mapModel(m, 'free-', `[Free] `, suffix);
174
167
  modelsOutput.push(mapped);
175
168
  });
176
169
  // 2. ENTERPRISE UNIVERSE
@@ -183,16 +176,17 @@ export async function generatePollinationsConfig(forceApiKey, forceStrict = fals
183
176
  enterList.forEach((m) => {
184
177
  if (m.tools === false)
185
178
  return;
186
- const mapped = mapModel(m, 'enter/', '[Enter] ');
179
+ const mapped = mapModel(m, 'enter-', '[Enter] ');
187
180
  modelsOutput.push(mapped);
188
181
  });
189
182
  log(`Total models (Free+Pro): ${modelsOutput.length}`);
183
+ log(`Generated IDs: ${modelsOutput.map(m => m.id).join(', ')}`);
190
184
  }
191
185
  catch (e) {
192
186
  log(`Error fetching Enterprise models: ${e}`);
193
187
  if (forceStrict)
194
188
  throw e;
195
- modelsOutput.push({ id: "enter/gpt-4o", name: "[Enter] GPT-4o (Fallback)", object: "model", variants: {} });
189
+ // STRICT: No Fallback for Enterprise. If API is down, we have 0 Enter models.
196
190
  }
197
191
  }
198
192
  return modelsOutput;
@@ -240,14 +234,16 @@ function mapModel(raw, prefix, namePrefix, nameSuffix = '') {
240
234
  const modelObj = {
241
235
  id: fullId,
242
236
  name: finalName,
243
- object: 'model',
244
- variants: {},
237
+ // object: 'model',
238
+ // variants: {}, // POTENTIAL SCHEMA VIOLATION
245
239
  modalities: {
246
240
  input: raw.input_modalities || ['text'],
247
241
  output: raw.output_modalities || ['text']
248
- }
242
+ },
243
+ tool_call: false // FORCE DEBUG DISABLE
249
244
  };
250
245
  // Enrichissements
246
+ /*
251
247
  if (raw.reasoning === true || rawId.includes('thinking') || rawId.includes('reasoning')) {
252
248
  modelObj.variants = { ...modelObj.variants, high_reasoning: { options: { reasoningEffort: "high", budgetTokens: 16000 } } };
253
249
  }
@@ -259,16 +255,24 @@ function mapModel(raw, prefix, namePrefix, nameSuffix = '') {
259
255
  if (rawId.includes('claude') || rawId.includes('mistral') || rawId.includes('llama')) {
260
256
  modelObj.variants.safe_tokens = { options: { maxTokens: 8000 } };
261
257
  }
258
+ */
262
259
  if (rawId.includes('nova')) {
263
- modelObj.limit = { output: 8000, context: 128000 };
264
- }
265
- if (rawId.includes('nomnom') || rawId.includes('scrape')) {
266
- modelObj.limit = { output: 2048, context: 32768 };
267
- }
260
+ if (rawId.includes('nova')) {
261
+ modelObj.limit = { output: 8000, context: 128000 };
262
+ }
263
+ if (rawId.includes('nomnom') || rawId.includes('scrape')) {
264
+ modelObj.limit = { output: 2048, context: 32768 };
265
+ }
266
+ if (rawId.includes('chicky')) {
267
+ modelObj.limit = { output: 8192, context: 8192 };
268
+ }
269
+ /*
268
270
  if (rawId.includes('fast') || rawId.includes('flash')) {
269
271
  if (!rawId.includes('gemini')) {
270
272
  modelObj.variants.speed = { options: { thinking: { disabled: true } } };
271
273
  }
272
274
  }
275
+ */
276
+ }
273
277
  return modelObj;
274
278
  }
@@ -0,0 +1,18 @@
1
+ export interface PollinationsModel {
2
+ name: string;
3
+ description?: string;
4
+ type?: string;
5
+ tools?: boolean;
6
+ reasoning?: boolean;
7
+ context?: number;
8
+ context_window?: number;
9
+ input_modalities?: string[];
10
+ output_modalities?: string[];
11
+ paid_only?: boolean;
12
+ vision?: boolean;
13
+ audio?: boolean;
14
+ community?: boolean;
15
+ censored?: boolean;
16
+ [key: string]: any;
17
+ }
18
+ export declare const FREE_MODELS_SEED: PollinationsModel[];
@@ -0,0 +1,55 @@
1
+ export const FREE_MODELS_SEED = [
2
+ {
3
+ "name": "gemini",
4
+ "description": "Gemini 2.5 Flash Lite",
5
+ "tier": "anonymous",
6
+ "tools": true,
7
+ "input_modalities": ["text", "image"],
8
+ "output_modalities": ["text"],
9
+ "vision": true
10
+ },
11
+ {
12
+ "name": "mistral",
13
+ "description": "Mistral Small 3.2 24B",
14
+ "tier": "anonymous",
15
+ "tools": true,
16
+ "input_modalities": ["text"],
17
+ "output_modalities": ["text"],
18
+ "vision": false
19
+ },
20
+ {
21
+ "name": "openai-fast",
22
+ "description": "GPT-OSS 20B Reasoning LLM (OVH)",
23
+ "tier": "anonymous",
24
+ "tools": true,
25
+ "input_modalities": ["text"],
26
+ "output_modalities": ["text"],
27
+ "vision": false,
28
+ "reasoning": true
29
+ },
30
+ {
31
+ "name": "bidara",
32
+ "description": "BIDARA (Biomimetic Designer)",
33
+ "tier": "anonymous",
34
+ "community": true,
35
+ "input_modalities": ["text", "image"],
36
+ "output_modalities": ["text"],
37
+ "vision": true
38
+ },
39
+ {
40
+ "name": "chickytutor",
41
+ "description": "ChickyTutor AI Language Tutor",
42
+ "tier": "anonymous",
43
+ "community": true,
44
+ "input_modalities": ["text"],
45
+ "output_modalities": ["text"]
46
+ },
47
+ {
48
+ "name": "midijourney",
49
+ "description": "MIDIjourney",
50
+ "tier": "anonymous",
51
+ "community": true,
52
+ "input_modalities": ["text"],
53
+ "output_modalities": ["text"]
54
+ }
55
+ ];
@@ -153,6 +153,11 @@ export async function handleChatCompletion(req, res, bodyRaw) {
153
153
  const config = loadConfig();
154
154
  // DEBUG: Trace Config State for Hot Reload verification
155
155
  log(`[Proxy Request] Config Loaded. Mode: ${config.mode}, HasKey: ${!!config.apiKey}, KeyLength: ${config.apiKey ? config.apiKey.length : 0}`);
156
+ // SPY LOGGING
157
+ try {
158
+ fs.appendFileSync('/tmp/opencode_spy.log', `\n\n=== REQUEST ${new Date().toISOString()} ===\nMODEL: ${body.model}\nBODY:\n${JSON.stringify(body, null, 2)}\n==========================\n`);
159
+ }
160
+ catch (e) { }
156
161
  // 0. COMMAND HANDLING
157
162
  if (body.messages && body.messages.length > 0) {
158
163
  const lastMsg = body.messages[body.messages.length - 1];
@@ -416,13 +421,32 @@ export async function handleChatCompletion(req, res, bodyRaw) {
416
421
  // Restore Tools but REMOVE conflicting ones (Search)
417
422
  // B. GEMINI UNIFIED FIX (Free, Fast, Pro, Enterprise, Legacy)
418
423
  // Handles: "tools" vs "grounding" conflicts, and "infinite loops" via Stop Sequences.
424
+ // GLOBAL BEDROCK FIX (All Models)
425
+ // Check if history has tools but current request misses tools definition.
426
+ // This happens when OpenCode sends the Tool Result (optimisation),
427
+ // but Bedrock requires toolConfig to validate the history.
428
+ const hasToolHistory = proxyBody.messages?.some((m) => m.role === 'tool' || m.tool_calls);
429
+ if (hasToolHistory && (!proxyBody.tools || proxyBody.tools.length === 0)) {
430
+ // Inject Shim Tool to satisfy Bedrock
431
+ proxyBody.tools = [{
432
+ type: 'function',
433
+ function: {
434
+ name: '_bedrock_compatibility_shim',
435
+ description: 'Internal system tool to satisfy Bedrock strict toolConfig requirement. Do not use.',
436
+ parameters: { type: 'object', properties: {} }
437
+ }
438
+ }];
439
+ log(`[Proxy] Bedrock Fix: Injected shim tool for ${actualModel} (History has tools, Request missing tools)`);
440
+ }
419
441
  // B. GEMINI UNIFIED FIX (Free, Fast, Pro, Enterprise, Legacy)
420
442
  // Fixes "Multiple tools" error (Vertex) and "JSON body validation failed" (v5.3.5 regression)
421
- else if (actualModel.includes("gemini")) {
443
+ // Added ChickyTutor (Claude/Gemini based) to fix "toolConfig must be defined" error.
444
+ else if (actualModel.includes("gemini") || actualModel.includes("chickytutor")) {
422
445
  let hasFunctions = false;
423
446
  if (proxyBody.tools && Array.isArray(proxyBody.tools)) {
424
447
  hasFunctions = proxyBody.tools.some((t) => t.type === 'function' || t.function);
425
448
  }
449
+ // Old Shim logic removed (moved up)
426
450
  if (hasFunctions) {
427
451
  // 1. Strict cleanup of 'google_search' tool
428
452
  proxyBody.tools = proxyBody.tools.filter((t) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opencode-pollinations-plugin",
3
3
  "displayName": "Pollinations AI (V5.6)",
4
- "version": "5.8.4-beta.1",
4
+ "version": "5.8.4-beta.10",
5
5
  "description": "Native Pollinations.ai Provider Plugin for OpenCode",
6
6
  "publisher": "pollinations",
7
7
  "repository": {