opencode-pollinations-plugin 5.8.4-beta.15 → 5.8.4-beta.3
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 +2 -6
- package/dist/server/generate-config.d.ts +2 -1
- package/dist/server/generate-config.js +14 -28
- package/dist/server/proxy.js +4 -36
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -99,16 +99,12 @@ export const PollinationsPlugin = async (ctx) => {
|
|
|
99
99
|
// Dynamic Provider Name
|
|
100
100
|
const version = require('../package.json').version;
|
|
101
101
|
config.provider['pollinations'] = {
|
|
102
|
-
id: '
|
|
102
|
+
id: 'pollinations',
|
|
103
103
|
name: `Pollinations AI (v${version})`,
|
|
104
|
-
options: {
|
|
105
|
-
baseURL: localBaseUrl,
|
|
106
|
-
apiKey: 'dummy-key', // Required by OpenAI provider
|
|
107
|
-
},
|
|
104
|
+
options: { baseURL: localBaseUrl },
|
|
108
105
|
models: modelsObj
|
|
109
106
|
};
|
|
110
107
|
log(`[Hook] Registered ${Object.keys(modelsObj).length} models.`);
|
|
111
|
-
log(`[Hook] Keys: ${Object.keys(modelsObj).join(', ')}`);
|
|
112
108
|
},
|
|
113
109
|
...toastHooks,
|
|
114
110
|
...createStatusHooks(ctx.client),
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
interface OpenCodeModel {
|
|
2
2
|
id: string;
|
|
3
3
|
name: string;
|
|
4
|
+
object: string;
|
|
5
|
+
variants?: any;
|
|
4
6
|
options?: any;
|
|
5
7
|
limit?: {
|
|
6
8
|
context?: number;
|
|
@@ -10,7 +12,6 @@ interface OpenCodeModel {
|
|
|
10
12
|
input?: string[];
|
|
11
13
|
output?: string[];
|
|
12
14
|
};
|
|
13
|
-
tool_call?: boolean;
|
|
14
15
|
}
|
|
15
16
|
export declare function generatePollinationsConfig(forceApiKey?: string, forceStrict?: boolean): Promise<OpenCodeModel[]>;
|
|
16
17
|
export {};
|
|
@@ -98,7 +98,7 @@ function saveCache(models, etag) {
|
|
|
98
98
|
export async function generatePollinationsConfig(forceApiKey, forceStrict = false) {
|
|
99
99
|
const config = loadConfig();
|
|
100
100
|
const modelsOutput = [];
|
|
101
|
-
log(`Starting Configuration (v5.8.4-
|
|
101
|
+
log(`Starting Configuration (v5.8.4-Beta2)...`);
|
|
102
102
|
const effectiveKey = forceApiKey || config.apiKey;
|
|
103
103
|
// 1. FREE UNIVERSE (Smart Cache System)
|
|
104
104
|
let freeModelsList = [];
|
|
@@ -163,7 +163,7 @@ export async function generatePollinationsConfig(forceApiKey, forceStrict = fals
|
|
|
163
163
|
// Tag (Offline) only if we explicitly failed a fetch attempt or are using Fallback SEED when fetch failed.
|
|
164
164
|
// If we use cache because it's valid (Skipped fetch), we don't tag (Offline).
|
|
165
165
|
const suffix = isOffline ? ' (Offline)' : '';
|
|
166
|
-
const mapped = mapModel(m, 'free
|
|
166
|
+
const mapped = mapModel(m, 'free/', `[Free] `, suffix);
|
|
167
167
|
modelsOutput.push(mapped);
|
|
168
168
|
});
|
|
169
169
|
// 2. ENTERPRISE UNIVERSE
|
|
@@ -176,11 +176,10 @@ export async function generatePollinationsConfig(forceApiKey, forceStrict = fals
|
|
|
176
176
|
enterList.forEach((m) => {
|
|
177
177
|
if (m.tools === false)
|
|
178
178
|
return;
|
|
179
|
-
const mapped = mapModel(m, 'enter
|
|
179
|
+
const mapped = mapModel(m, 'enter/', '[Enter] ');
|
|
180
180
|
modelsOutput.push(mapped);
|
|
181
181
|
});
|
|
182
182
|
log(`Total models (Free+Pro): ${modelsOutput.length}`);
|
|
183
|
-
log(`Generated IDs: ${modelsOutput.map(m => m.id).join(', ')}`);
|
|
184
183
|
}
|
|
185
184
|
catch (e) {
|
|
186
185
|
log(`Error fetching Enterprise models: ${e}`);
|
|
@@ -234,16 +233,14 @@ function mapModel(raw, prefix, namePrefix, nameSuffix = '') {
|
|
|
234
233
|
const modelObj = {
|
|
235
234
|
id: fullId,
|
|
236
235
|
name: finalName,
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
object: 'model',
|
|
237
|
+
variants: {},
|
|
239
238
|
modalities: {
|
|
240
239
|
input: raw.input_modalities || ['text'],
|
|
241
240
|
output: raw.output_modalities || ['text']
|
|
242
|
-
}
|
|
243
|
-
tool_call: false // FORCE DEBUG DISABLE
|
|
241
|
+
}
|
|
244
242
|
};
|
|
245
243
|
// Enrichissements
|
|
246
|
-
/*
|
|
247
244
|
if (raw.reasoning === true || rawId.includes('thinking') || rawId.includes('reasoning')) {
|
|
248
245
|
modelObj.variants = { ...modelObj.variants, high_reasoning: { options: { reasoningEffort: "high", budgetTokens: 16000 } } };
|
|
249
246
|
}
|
|
@@ -255,30 +252,19 @@ function mapModel(raw, prefix, namePrefix, nameSuffix = '') {
|
|
|
255
252
|
if (rawId.includes('claude') || rawId.includes('mistral') || rawId.includes('llama')) {
|
|
256
253
|
modelObj.variants.safe_tokens = { options: { maxTokens: 8000 } };
|
|
257
254
|
}
|
|
258
|
-
*/
|
|
259
255
|
if (rawId.includes('nova')) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
modelObj.options = { ...modelObj.options, maxTokens: 4096 };
|
|
269
|
-
log(`[LimitConfig] Applied strict limit to ${fullId}: output=4096, context=8192`);
|
|
270
|
-
}
|
|
271
|
-
/*
|
|
256
|
+
modelObj.limit = { output: 8000, context: 128000 };
|
|
257
|
+
}
|
|
258
|
+
if (rawId.includes('nomnom') || rawId.includes('scrape')) {
|
|
259
|
+
modelObj.limit = { output: 2048, context: 32768 };
|
|
260
|
+
}
|
|
261
|
+
if (rawId.includes('chicky')) {
|
|
262
|
+
modelObj.limit = { output: 8192, context: 8192 };
|
|
263
|
+
}
|
|
272
264
|
if (rawId.includes('fast') || rawId.includes('flash')) {
|
|
273
265
|
if (!rawId.includes('gemini')) {
|
|
274
266
|
modelObj.variants.speed = { options: { thinking: { disabled: true } } };
|
|
275
267
|
}
|
|
276
268
|
}
|
|
277
|
-
*/
|
|
278
|
-
}
|
|
279
|
-
// DEBUG LIMITS
|
|
280
|
-
if (modelObj.limit) {
|
|
281
|
-
log(`[Model] ${modelObj.id} Limit: ${JSON.stringify(modelObj.limit)}`);
|
|
282
|
-
}
|
|
283
269
|
return modelObj;
|
|
284
270
|
}
|
package/dist/server/proxy.js
CHANGED
|
@@ -153,11 +153,6 @@ 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) { }
|
|
161
156
|
// 0. COMMAND HANDLING
|
|
162
157
|
if (body.messages && body.messages.length > 0) {
|
|
163
158
|
const lastMsg = body.messages[body.messages.length - 1];
|
|
@@ -217,14 +212,13 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
217
212
|
const { getQuotaStatus, formatQuotaForToast } = await import('./quota.js');
|
|
218
213
|
const quota = await getQuotaStatus(false);
|
|
219
214
|
// A. Resolve Base Target
|
|
220
|
-
|
|
221
|
-
if (actualModel.startsWith('enter/') || actualModel.startsWith('enter-')) {
|
|
215
|
+
if (actualModel.startsWith('enter/')) {
|
|
222
216
|
isEnterprise = true;
|
|
223
|
-
actualModel = actualModel.replace(
|
|
217
|
+
actualModel = actualModel.replace('enter/', '');
|
|
224
218
|
}
|
|
225
|
-
else if (actualModel.startsWith('free/')
|
|
219
|
+
else if (actualModel.startsWith('free/')) {
|
|
226
220
|
isEnterprise = false;
|
|
227
|
-
actualModel = actualModel.replace(
|
|
221
|
+
actualModel = actualModel.replace('free/', '');
|
|
228
222
|
}
|
|
229
223
|
// A.1 PAID MODEL ENFORCEMENT (V5.5 Strategy)
|
|
230
224
|
// Check dynamic list saved by generate-config.ts
|
|
@@ -422,23 +416,6 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
422
416
|
// Restore Tools but REMOVE conflicting ones (Search)
|
|
423
417
|
// B. GEMINI UNIFIED FIX (Free, Fast, Pro, Enterprise, Legacy)
|
|
424
418
|
// Handles: "tools" vs "grounding" conflicts, and "infinite loops" via Stop Sequences.
|
|
425
|
-
// GLOBAL BEDROCK FIX (All Models)
|
|
426
|
-
// Check if history has tools but current request misses tools definition.
|
|
427
|
-
// This happens when OpenCode sends the Tool Result (optimisation),
|
|
428
|
-
// but Bedrock requires toolConfig to validate the history.
|
|
429
|
-
const hasToolHistory = proxyBody.messages?.some((m) => m.role === 'tool' || m.tool_calls);
|
|
430
|
-
if (hasToolHistory && (!proxyBody.tools || proxyBody.tools.length === 0)) {
|
|
431
|
-
// Inject Shim Tool to satisfy Bedrock
|
|
432
|
-
proxyBody.tools = [{
|
|
433
|
-
type: 'function',
|
|
434
|
-
function: {
|
|
435
|
-
name: '_bedrock_compatibility_shim',
|
|
436
|
-
description: 'Internal system tool to satisfy Bedrock strict toolConfig requirement. Do not use.',
|
|
437
|
-
parameters: { type: 'object', properties: {} }
|
|
438
|
-
}
|
|
439
|
-
}];
|
|
440
|
-
log(`[Proxy] Bedrock Fix: Injected shim tool for ${actualModel} (History has tools, Request missing tools)`);
|
|
441
|
-
}
|
|
442
419
|
// B. GEMINI UNIFIED FIX (Free, Fast, Pro, Enterprise, Legacy)
|
|
443
420
|
// Fixes "Multiple tools" error (Vertex) and "JSON body validation failed" (v5.3.5 regression)
|
|
444
421
|
// Added ChickyTutor (Claude/Gemini based) to fix "toolConfig must be defined" error.
|
|
@@ -447,7 +424,6 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
447
424
|
if (proxyBody.tools && Array.isArray(proxyBody.tools)) {
|
|
448
425
|
hasFunctions = proxyBody.tools.some((t) => t.type === 'function' || t.function);
|
|
449
426
|
}
|
|
450
|
-
// Old Shim logic removed (moved up)
|
|
451
427
|
if (hasFunctions) {
|
|
452
428
|
// 1. Strict cleanup of 'google_search' tool
|
|
453
429
|
proxyBody.tools = proxyBody.tools.filter((t) => {
|
|
@@ -478,14 +454,6 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
478
454
|
log(`[Proxy] Gemini Logic: Tools=${proxyBody.tools ? proxyBody.tools.length : 'REMOVED'}, Stops NOT Injected.`);
|
|
479
455
|
}
|
|
480
456
|
}
|
|
481
|
-
// B5. BEDROCK TOKEN LIMIT FIX
|
|
482
|
-
if (actualModel.includes("chicky") || actualModel.includes("mistral")) {
|
|
483
|
-
// Force max_tokens if not present or too high (Bedrock outputs usually max 4k, context 8k+ but strict check)
|
|
484
|
-
if (!proxyBody.max_tokens || proxyBody.max_tokens > 4096) {
|
|
485
|
-
proxyBody.max_tokens = 4096;
|
|
486
|
-
log(`[Proxy] Enforcing max_tokens=4096 for ${actualModel} (Bedrock Limit)`);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
457
|
// C. GEMINI ID BACKTRACKING & SIGNATURE
|
|
490
458
|
if ((actualModel.includes("gemini") || actualModel === "nomnom") && proxyBody.messages) {
|
|
491
459
|
const lastMsg = proxyBody.messages[proxyBody.messages.length - 1];
|
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.3",
|
|
5
5
|
"description": "Native Pollinations.ai Provider Plugin for OpenCode",
|
|
6
6
|
"publisher": "pollinations",
|
|
7
7
|
"repository": {
|