maxpool 1.5.73 → 1.5.75
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 +37 -16
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -1043,7 +1043,18 @@ async function forwardRequest(
|
|
|
1043
1043
|
// self-heals instead of poisoning the session into a 400 loop. Signatures are
|
|
1044
1044
|
// portable in practice (verified 2026-07-02); this only fires if Anthropic
|
|
1045
1045
|
// ever account-binds them.
|
|
1046
|
-
|
|
1046
|
+
// ONLY for a Claude→Claude migration. When the issuer is a PROVIDER, reverting
|
|
1047
|
+
// there is not a repair — the provider happily serves the request, but the
|
|
1048
|
+
// transcript keeps its provider-authored thinking blocks, so the very next turn
|
|
1049
|
+
// that routes back to Claude 400s on the SAME block. Measured 2026-08-09: the
|
|
1050
|
+
// same coordinate (messages.5.content.23) failed 4 times in 2 minutes, each one
|
|
1051
|
+
// "reverting to issuer glm max@gomokka.com" and never repairing anything.
|
|
1052
|
+
// The correct repair for a provider-authored block is the strip below.
|
|
1053
|
+
const issuer = lease.migratedFromName
|
|
1054
|
+
? accountManager.accounts?.find(a => a.name === lease.migratedFromName)
|
|
1055
|
+
: null;
|
|
1056
|
+
const issuerIsClaude = issuer && issuer.type !== 'provider';
|
|
1057
|
+
if (lease.migratedFromName && issuerIsClaude && requestInfo.sessionKey
|
|
1047
1058
|
&& canRetryBufferedBody && retryCount + 1 < maxAttempts && !res.headersSent) {
|
|
1048
1059
|
accountManager.revertSessionBinding(requestInfo.sessionKey, lease.migratedFromName);
|
|
1049
1060
|
excludedIndexes.add(account.index);
|
|
@@ -1082,8 +1093,14 @@ async function forwardRequest(
|
|
|
1082
1093
|
// its life. Verified against the real API — the stripped history returns 200, with
|
|
1083
1094
|
// text + tool_use preserved. Tried once per request (thinkingStripped guard); if it
|
|
1084
1095
|
// still fails, the provider pin below is the fallback.
|
|
1085
|
-
|
|
1086
|
-
|
|
1096
|
+
// NOT gated on canRetryBufferedBody. That limit exists to stop a huge body being
|
|
1097
|
+
// re-sent across accounts on a FAILOVER — but a repair SHRINKS the body (measured:
|
|
1098
|
+
// 11.5MB → 5.7MB in 20ms) and is the only thing standing between the user and a
|
|
1099
|
+
// dead session. The body is already fully in memory by this point, so refusing to
|
|
1100
|
+
// rewrite it saves nothing; it just guarantees the 400 surfaces. Reported
|
|
1101
|
+
// 2026-08-10: "history too large to rewrite automatically" on a session the strip
|
|
1102
|
+
// would have fixed in 20ms. The retry it schedules re-checks the SHRUNK size.
|
|
1103
|
+
if (isSignatureRejection && !requestInfo.thinkingStripped && canRepairBody) {
|
|
1087
1104
|
console.log(`[Maxpool] Anthropic rejected a block: ${describeRejectedBlock(body, errorBody)}`);
|
|
1088
1105
|
const { body: cleanBody, removed, converted } = stripForeignThinkingBlocks(body);
|
|
1089
1106
|
if (cleanBody) {
|
|
@@ -1091,10 +1108,14 @@ async function forwardRequest(
|
|
|
1091
1108
|
// rejected round-trip (the client resends the full poisoned history each turn).
|
|
1092
1109
|
accountManager.markSessionThinkingContaminated?.(requestInfo.sessionKey);
|
|
1093
1110
|
console.log(`[Maxpool] Recovering session on Claude: stripped ${removed} provider thinking block(s), converted ${converted} provider search block(s) to text`);
|
|
1111
|
+
// Re-derive the retry budget from the SHRUNK body. Inheriting the old flag
|
|
1112
|
+
// would leave a now-5.7MB body permanently marked "too big to retry" because
|
|
1113
|
+
// it was 11.5MB before the repair — barring the very failover the repair
|
|
1114
|
+
// exists to enable.
|
|
1094
1115
|
return forwardRequest(
|
|
1095
1116
|
req, res, cleanBody, accountManager, upstream, retryCount + 1, hooks, reqId, ctx, logDir,
|
|
1096
1117
|
retryConfig, queueConfig, { ...requestInfo, thinkingStripped: true, repairCount: repairCount + 1 },
|
|
1097
|
-
|
|
1118
|
+
cleanBody.length <= retryConfig.maxRetryBufferBytes, canQueueBufferedBody, excludedIndexes,
|
|
1098
1119
|
);
|
|
1099
1120
|
}
|
|
1100
1121
|
}
|
|
@@ -1102,7 +1123,9 @@ async function forwardRequest(
|
|
|
1102
1123
|
// COORDINATE REPAIR (runs after the broad strip found nothing, or found the wrong
|
|
1103
1124
|
// thing). Anthropic pointed at an exact block index; trust that over our own shape
|
|
1104
1125
|
// model. Its own flag, so it still fires on a request whose broad strip already ran.
|
|
1105
|
-
|
|
1126
|
+
// Same reasoning as the broad strip above: a repair SHRINKS the body, so the
|
|
1127
|
+
// re-send limit must not bar it.
|
|
1128
|
+
if (isSignatureRejection && !requestInfo.rejectedBlockStripped && canRepairBody) {
|
|
1106
1129
|
const { body: fixedBody, removed, type } = stripRejectedBlockClass(body, errorBody);
|
|
1107
1130
|
if (fixedBody) {
|
|
1108
1131
|
// Latch the session ONLY for the class the pre-strip can actually repair up
|
|
@@ -1122,7 +1145,7 @@ async function forwardRequest(
|
|
|
1122
1145
|
thinkingStripped: preStripCanRepeat || requestInfo.thinkingStripped,
|
|
1123
1146
|
repairCount: repairCount + 1,
|
|
1124
1147
|
},
|
|
1125
|
-
|
|
1148
|
+
fixedBody.length <= retryConfig.maxRetryBufferBytes, canQueueBufferedBody, excludedIndexes,
|
|
1126
1149
|
);
|
|
1127
1150
|
}
|
|
1128
1151
|
}
|
|
@@ -1187,16 +1210,14 @@ async function forwardRequest(
|
|
|
1187
1210
|
// and without it the two surviving explanations (a block the strip cannot see
|
|
1188
1211
|
// vs. a body over the retry buffer) are indistinguishable in the log.
|
|
1189
1212
|
console.log(`[Maxpool] Unrepaired signature 400: ${describeRejectedBlock(body, errorBody)} bufferable=${canRetryBufferedBody} stripped=${!!requestInfo.thinkingStripped}`);
|
|
1190
|
-
//
|
|
1191
|
-
//
|
|
1192
|
-
//
|
|
1193
|
-
//
|
|
1194
|
-
|
|
1195
|
-
//
|
|
1196
|
-
|
|
1197
|
-
const what =
|
|
1198
|
-
? `This session's history is too large for maxpool to rewrite automatically (over ${Math.round(retryConfig.maxRetryBufferBytes / (1024 * 1024))}MB). Run /compact and it will keep going.`
|
|
1199
|
-
: rejectedType && rejectedType !== 'thinking' && rejectedType !== 'redacted_thinking'
|
|
1213
|
+
// `peek` (not the full class-strip) — reads only `.type`, no parse+rebuild.
|
|
1214
|
+
// Read it regardless of body size: the repairs are no longer size-gated, so a
|
|
1215
|
+
// large body reaches here for a REAL reason (an unremovable block type) and the
|
|
1216
|
+
// user deserves to be told which one.
|
|
1217
|
+
const rejectedType = peekRejectedBlockType(body, errorBody);
|
|
1218
|
+
// NOTE: no "too large to rewrite" branch any more — the repairs above are no
|
|
1219
|
+
// longer gated on canRetryBufferedBody, so size never blocks a repair attempt.
|
|
1220
|
+
const what = rejectedType && rejectedType !== 'thinking' && rejectedType !== 'redacted_thinking'
|
|
1200
1221
|
? `Anthropic rejected a "${rejectedType}" block in this session's history, which maxpool cannot remove without losing conversation content.`
|
|
1201
1222
|
: requestInfo.thinkingStripped || requestInfo.rejectedBlockStripped
|
|
1202
1223
|
? 'This session ran on GLM/Kimi earlier, and Anthropic will not accept parts of what they wrote. Maxpool repaired what it could and retried on Claude, but Anthropic still rejected the history.'
|