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
|
|
11
|
-
|
|
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-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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
|
+
];
|
package/dist/server/proxy.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
4
|
+
"version": "5.8.4-beta.10",
|
|
5
5
|
"description": "Native Pollinations.ai Provider Plugin for OpenCode",
|
|
6
6
|
"publisher": "pollinations",
|
|
7
7
|
"repository": {
|