opencode-pollinations-plugin 6.1.0-beta.4 → 6.1.0-beta.6
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/server/commands.js +18 -17
- package/dist/server/proxy.js +79 -1
- package/package.json +1 -1
package/dist/server/commands.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as https from 'https';
|
|
|
2
2
|
import { loadConfig, saveConfig } from './config.js';
|
|
3
3
|
import { getQuotaStatus } from './quota.js';
|
|
4
4
|
import { emitStatusToast } from './toast.js';
|
|
5
|
-
import { getDetailedUsage } from './pollinations-api.js';
|
|
5
|
+
import { getDetailedUsage, getAggregatedModels } from './pollinations-api.js';
|
|
6
6
|
import { generatePollinationsConfig } from './generate-config.js';
|
|
7
7
|
function checkEndpoint(ep, key) {
|
|
8
8
|
return new Promise((resolve) => {
|
|
@@ -145,7 +145,7 @@ export async function handleCommand(command) {
|
|
|
145
145
|
case 'connect':
|
|
146
146
|
return await handleConnectCommand(args);
|
|
147
147
|
case 'fallback':
|
|
148
|
-
return handleFallbackCommand(args);
|
|
148
|
+
return await handleFallbackCommand(args);
|
|
149
149
|
case 'config':
|
|
150
150
|
return handleConfigCommand(args);
|
|
151
151
|
case 'help':
|
|
@@ -265,7 +265,7 @@ async function handleUsageCommand(args) {
|
|
|
265
265
|
return { handled: true, error: `Erreur: ${e}` };
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
-
function handleFallbackCommand(args) {
|
|
268
|
+
async function handleFallbackCommand(args) {
|
|
269
269
|
let targetMode = args[0];
|
|
270
270
|
const targetModel = args[1];
|
|
271
271
|
if (!targetMode || !targetModel) {
|
|
@@ -280,20 +280,21 @@ function handleFallbackCommand(args) {
|
|
|
280
280
|
if (targetMode !== 'economy' && targetMode !== 'pro') {
|
|
281
281
|
return { handled: true, error: 'Target mode invalide (economy ou pro)' };
|
|
282
282
|
}
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
283
|
+
// DYNAMIC MODEL VALIDATION (BUG 2 FIX)
|
|
284
|
+
try {
|
|
285
|
+
const { data: models } = await getAggregatedModels();
|
|
286
|
+
const validIds = models.map(m => m.id.replace(/^pollinations\/(free|enter)\//, ''));
|
|
287
|
+
if (!validIds.includes(targetModel)) {
|
|
288
|
+
const suggestions = validIds.slice(0, 10).join(', ');
|
|
289
|
+
return {
|
|
290
|
+
handled: true,
|
|
291
|
+
error: `⚠️ Modèle inconnu: "${targetModel}".\nExemples valides: ${suggestions}...`
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
// Fail-open si API down
|
|
297
|
+
console.warn('[Fallback] Model validation failed, allowing:', e);
|
|
297
298
|
}
|
|
298
299
|
const config = loadConfig();
|
|
299
300
|
const updates = { fallbacks: { ...config.fallbacks } };
|
package/dist/server/proxy.js
CHANGED
|
@@ -112,6 +112,75 @@ function truncateTools(tools, limit = 120) {
|
|
|
112
112
|
return tools;
|
|
113
113
|
return tools.slice(0, limit);
|
|
114
114
|
}
|
|
115
|
+
// --- BEDROCK COMPATIBILITY SHIM ---
|
|
116
|
+
// Bedrock requires:
|
|
117
|
+
// 1. toolUseId matching [a-zA-Z0-9_-]+ (no dots, spaces, special chars)
|
|
118
|
+
// 2. toolConfig present when toolUse/toolResult in messages
|
|
119
|
+
function sanitizeToolUseId(id) {
|
|
120
|
+
// Replace any char not in [a-zA-Z0-9_-] with underscore
|
|
121
|
+
return id.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
122
|
+
}
|
|
123
|
+
function sanitizeForBedrock(body) {
|
|
124
|
+
if (!body)
|
|
125
|
+
return body;
|
|
126
|
+
const sanitized = JSON.parse(JSON.stringify(body)); // Deep clone
|
|
127
|
+
// 1. Sanitize toolUseId in all messages
|
|
128
|
+
if (sanitized.messages && Array.isArray(sanitized.messages)) {
|
|
129
|
+
for (const msg of sanitized.messages) {
|
|
130
|
+
if (msg.content && Array.isArray(msg.content)) {
|
|
131
|
+
for (const block of msg.content) {
|
|
132
|
+
// Handle toolUse blocks
|
|
133
|
+
if (block.toolUse && block.toolUse.toolUseId) {
|
|
134
|
+
block.toolUse.toolUseId = sanitizeToolUseId(block.toolUse.toolUseId);
|
|
135
|
+
}
|
|
136
|
+
// Handle toolResult blocks
|
|
137
|
+
if (block.toolResult && block.toolResult.toolUseId) {
|
|
138
|
+
block.toolResult.toolUseId = sanitizeToolUseId(block.toolResult.toolUseId);
|
|
139
|
+
}
|
|
140
|
+
// Handle OpenAI-style tool_calls
|
|
141
|
+
if (block.type === 'tool_use' && block.id) {
|
|
142
|
+
block.id = sanitizeToolUseId(block.id);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Handle assistant tool_calls array (OpenAI format)
|
|
147
|
+
if (msg.tool_calls && Array.isArray(msg.tool_calls)) {
|
|
148
|
+
for (const tc of msg.tool_calls) {
|
|
149
|
+
if (tc.id)
|
|
150
|
+
tc.id = sanitizeToolUseId(tc.id);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Handle tool role message (OpenAI format)
|
|
154
|
+
if (msg.role === 'tool' && msg.tool_call_id) {
|
|
155
|
+
msg.tool_call_id = sanitizeToolUseId(msg.tool_call_id);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// 2. Add toolConfig if tools present but toolConfig missing
|
|
160
|
+
if (sanitized.tools && Array.isArray(sanitized.tools) && sanitized.tools.length > 0) {
|
|
161
|
+
if (!sanitized.tool_config && !sanitized.toolConfig) {
|
|
162
|
+
// Build toolConfig from tools array (Bedrock Converse format)
|
|
163
|
+
sanitized.tool_config = {
|
|
164
|
+
tools: sanitized.tools.map((t) => {
|
|
165
|
+
if (t.function) {
|
|
166
|
+
// OpenAI format -> Bedrock format
|
|
167
|
+
return {
|
|
168
|
+
toolSpec: {
|
|
169
|
+
name: t.function.name,
|
|
170
|
+
description: t.function.description || '',
|
|
171
|
+
inputSchema: {
|
|
172
|
+
json: t.function.parameters || { type: 'object', properties: {} }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return t; // Already in Bedrock format
|
|
178
|
+
})
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return sanitized;
|
|
183
|
+
}
|
|
115
184
|
const MAX_RETRIES = 3;
|
|
116
185
|
const RETRY_DELAY_MS = 1000;
|
|
117
186
|
function sleep(ms) {
|
|
@@ -647,11 +716,20 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
647
716
|
log(`[SafetyNet] Adjusted max_tokens to 4000 for ${actualModel}`);
|
|
648
717
|
}
|
|
649
718
|
}
|
|
719
|
+
// BEDROCK COMPATIBILITY SHIM (BUG 1 - Proper Transform)
|
|
720
|
+
const isBedrockModel = actualModel.includes('nova') ||
|
|
721
|
+
actualModel.includes('amazon') ||
|
|
722
|
+
actualModel.includes('chickytutor');
|
|
723
|
+
let finalRetryBody = retryBody;
|
|
724
|
+
if (isBedrockModel) {
|
|
725
|
+
finalRetryBody = sanitizeForBedrock(retryBody);
|
|
726
|
+
log(`[SafetyNet] Applied Bedrock shim for ${actualModel}`);
|
|
727
|
+
}
|
|
650
728
|
// 4. Retry Fetch
|
|
651
729
|
const retryRes = await fetchWithRetry(targetUrl, {
|
|
652
730
|
method: 'POST',
|
|
653
731
|
headers: retryHeaders,
|
|
654
|
-
body: JSON.stringify(
|
|
732
|
+
body: JSON.stringify(finalRetryBody)
|
|
655
733
|
});
|
|
656
734
|
if (retryRes.ok) {
|
|
657
735
|
res.statusCode = retryRes.status;
|
package/package.json
CHANGED