opencode-pollinations-plugin 6.1.0-beta.5 → 6.1.0-beta.7
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/proxy.js +84 -7
- package/package.json +1 -1
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) {
|
|
@@ -587,10 +656,18 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
587
656
|
if (authHeader)
|
|
588
657
|
headers['Authorization'] = authHeader;
|
|
589
658
|
// 5. Forward (Global Fetch with Retry)
|
|
659
|
+
// BEDROCK COMPATIBILITY: Apply transformation BEFORE first request
|
|
660
|
+
const isBedrockModel = actualModel.includes('nova') ||
|
|
661
|
+
actualModel.includes('amazon') ||
|
|
662
|
+
actualModel.includes('chickytutor');
|
|
663
|
+
const finalProxyBody = isBedrockModel ? sanitizeForBedrock(proxyBody) : proxyBody;
|
|
664
|
+
if (isBedrockModel) {
|
|
665
|
+
log(`[Proxy] Applied Bedrock shim for ${actualModel} (Initial Request)`);
|
|
666
|
+
}
|
|
590
667
|
const fetchRes = await fetchWithRetry(targetUrl, {
|
|
591
668
|
method: 'POST',
|
|
592
669
|
headers: headers,
|
|
593
|
-
body: JSON.stringify(
|
|
670
|
+
body: JSON.stringify(finalProxyBody)
|
|
594
671
|
});
|
|
595
672
|
res.statusCode = fetchRes.status;
|
|
596
673
|
fetchRes.headers.forEach((val, key) => {
|
|
@@ -647,20 +724,20 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
647
724
|
log(`[SafetyNet] Adjusted max_tokens to 4000 for ${actualModel}`);
|
|
648
725
|
}
|
|
649
726
|
}
|
|
650
|
-
// BEDROCK COMPATIBILITY
|
|
727
|
+
// BEDROCK COMPATIBILITY SHIM (BUG 1 - Proper Transform)
|
|
651
728
|
const isBedrockModel = actualModel.includes('nova') ||
|
|
652
729
|
actualModel.includes('amazon') ||
|
|
653
730
|
actualModel.includes('chickytutor');
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
731
|
+
let finalRetryBody = retryBody;
|
|
732
|
+
if (isBedrockModel) {
|
|
733
|
+
finalRetryBody = sanitizeForBedrock(retryBody);
|
|
734
|
+
log(`[SafetyNet] Applied Bedrock shim for ${actualModel}`);
|
|
658
735
|
}
|
|
659
736
|
// 4. Retry Fetch
|
|
660
737
|
const retryRes = await fetchWithRetry(targetUrl, {
|
|
661
738
|
method: 'POST',
|
|
662
739
|
headers: retryHeaders,
|
|
663
|
-
body: JSON.stringify(
|
|
740
|
+
body: JSON.stringify(finalRetryBody)
|
|
664
741
|
});
|
|
665
742
|
if (retryRes.ok) {
|
|
666
743
|
res.statusCode = retryRes.status;
|
package/package.json
CHANGED