maxpool 1.19.6 → 1.19.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/package.json +1 -1
- package/src/server.js +39 -3
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -1757,7 +1757,7 @@ function isContextLengthError(errorBody) {
|
|
|
1757
1757
|
return /exceeded model token limit|maximum context length|context length exceeded|context window (?:size )?(?:exceeded|too)|prompt is too long|input is too long|reduce the length of|too many (?:input )?tokens|request too large/i.test(errorBody);
|
|
1758
1758
|
}
|
|
1759
1759
|
|
|
1760
|
-
export const __serverTest = { reanchorOrphanedSystemMessages, unavailableMessage, computeQueueWindowMs, isRetriableUpstreamStatus, classifyEffortRejection, repairEffort, isCapacitySignalStatus, isStrippableThinkingBlock, stripForeignThinkingBlocks, parseRejectedBlockPath, stripRejectedBlockClass, peekRejectedBlockType, describeRejectedBlock, headerValue, getMaxpoolProfile, ensureQueueHeartbeat, clearQueueHeartbeat, commitStreamGraceHeartbeat, describeRequest, classifyRateLimit, detectTranscriptOrigin, isAnthropicIncompatBody, isContextLengthError, isProviderParamRejection, describeBodyShape, streamResponse, startIdleRequestReaper, normalizeModelEcho };
|
|
1760
|
+
export const __serverTest = { rewriteBodyForAccount, sanitizeBlocksForProvider, reanchorOrphanedSystemMessages, unavailableMessage, computeQueueWindowMs, isRetriableUpstreamStatus, classifyEffortRejection, repairEffort, isCapacitySignalStatus, isStrippableThinkingBlock, stripForeignThinkingBlocks, parseRejectedBlockPath, stripRejectedBlockClass, peekRejectedBlockType, describeRejectedBlock, headerValue, getMaxpoolProfile, ensureQueueHeartbeat, clearQueueHeartbeat, commitStreamGraceHeartbeat, describeRequest, classifyRateLimit, detectTranscriptOrigin, isAnthropicIncompatBody, isContextLengthError, isProviderParamRejection, describeBodyShape, streamResponse, startIdleRequestReaper, normalizeModelEcho };
|
|
1761
1761
|
|
|
1762
1762
|
async function readErrorBody(upstreamRes, limitBytes = 64 * 1024) {
|
|
1763
1763
|
if (!upstreamRes.body) return '';
|
|
@@ -2957,18 +2957,54 @@ const threadOwners = new ThreadOwners();
|
|
|
2957
2957
|
const THREAD_GATE_ENABLED = process.env.MAXPOOL_THREAD_GATE !== '0';
|
|
2958
2958
|
|
|
2959
2959
|
function rewriteBodyForAccount(body, account) {
|
|
2960
|
-
|
|
2960
|
+
const needsProviderSanitize = account.type === 'provider';
|
|
2961
|
+
if (!body.length || (!account.model && !account.modelMap && !needsProviderSanitize)) return body;
|
|
2961
2962
|
|
|
2962
2963
|
try {
|
|
2963
2964
|
const json = JSON.parse(body.toString());
|
|
2964
2965
|
if (!json || typeof json !== 'object' || !json.model) return body;
|
|
2965
|
-
json.model = mappedModel(json.model, account);
|
|
2966
|
+
if (account.model || account.modelMap) json.model = mappedModel(json.model, account);
|
|
2967
|
+
if (needsProviderSanitize) sanitizeBlocksForProvider(json);
|
|
2966
2968
|
return Buffer.from(JSON.stringify(json));
|
|
2967
2969
|
} catch {
|
|
2968
2970
|
return body;
|
|
2969
2971
|
}
|
|
2970
2972
|
}
|
|
2971
2973
|
|
|
2974
|
+
// Content-block types Anthropic's own client emits that a provider's validator rejects
|
|
2975
|
+
// outright, taking the WHOLE request with it. Measured 2026-09-13 against z.ai: a body
|
|
2976
|
+
// carrying one `tool_reference` block (Claude Code writes these into `tool_result` when
|
|
2977
|
+
// ToolSearch loads a deferred tool) returns `[1210] Invalid API parameter` — the entire
|
|
2978
|
+
// 5.5MB transcript refused over 12 blocks. Counterfactual on the owner's real failing
|
|
2979
|
+
// session: identical body with ONLY these blocks rewritten to text returned 200 OK.
|
|
2980
|
+
//
|
|
2981
|
+
// It is not a size or token limit — z.ai has a distinct code for that (`[1261] Prompt
|
|
2982
|
+
// too long`), and a 34KB body with the block fails while 5.5MB without it passes.
|
|
2983
|
+
//
|
|
2984
|
+
// We rewrite rather than drop: the block carries a tool NAME the conversation refers to,
|
|
2985
|
+
// so replacing it with the equivalent sentence keeps the transcript truthful. Anthropic
|
|
2986
|
+
// accounts are untouched — they understand the block natively.
|
|
2987
|
+
const PROVIDER_UNSUPPORTED_BLOCKS = new Set(['tool_reference']);
|
|
2988
|
+
|
|
2989
|
+
function sanitizeBlocksForProvider(json) {
|
|
2990
|
+
const messages = json?.messages;
|
|
2991
|
+
if (!Array.isArray(messages)) return;
|
|
2992
|
+
for (const message of messages) {
|
|
2993
|
+
const content = message?.content;
|
|
2994
|
+
if (!Array.isArray(content)) continue;
|
|
2995
|
+
for (const block of content) {
|
|
2996
|
+
// The blocks live INSIDE tool_result content, not at the message top level.
|
|
2997
|
+
if (!block || typeof block !== 'object' || !Array.isArray(block.content)) continue;
|
|
2998
|
+
for (let i = 0; i < block.content.length; i++) {
|
|
2999
|
+
const inner = block.content[i];
|
|
3000
|
+
if (!inner || typeof inner !== 'object') continue;
|
|
3001
|
+
if (!PROVIDER_UNSUPPORTED_BLOCKS.has(inner.type)) continue;
|
|
3002
|
+
block.content[i] = { type: 'text', text: `Tool loaded: ${inner.tool_name || 'unknown'}` };
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
|
|
2972
3008
|
function mappedModel(originalModel, account) {
|
|
2973
3009
|
if (account.model) return account.model;
|
|
2974
3010
|
const map = account.modelMap || {};
|