maxpool 1.5.29 → 1.5.31
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/account-manager.js +7 -0
- package/src/server.js +23 -2
- package/src/tui.js +8 -1
package/package.json
CHANGED
package/src/account-manager.js
CHANGED
|
@@ -1609,6 +1609,13 @@ export class AccountManager {
|
|
|
1609
1609
|
_isRequestCompatible(account, profile, requestInfo = {}) {
|
|
1610
1610
|
if (!this._matchesProfile(account, profile)) return false;
|
|
1611
1611
|
|
|
1612
|
+
// Kimi (Moonshot) 400s on images Anthropic/GLM accept ("failed to decode
|
|
1613
|
+
// image") — and a provider 400 is TERMINAL (not retried to another account), so
|
|
1614
|
+
// an image request that fell back to Kimi FAILS the whole request. Keep image
|
|
1615
|
+
// requests off Kimi; they still route to GLM (handles images) + OAuth. If those
|
|
1616
|
+
// are all unavailable the request HOLDS/queues (recoverable) rather than 400ing.
|
|
1617
|
+
if (requestInfo.hasImage && account.provider === 'kimi') return false;
|
|
1618
|
+
|
|
1612
1619
|
const { incompatible, homeProvider } = this._effectiveIncompatible(requestInfo);
|
|
1613
1620
|
const policy = this._crossProviderFallbackPolicy();
|
|
1614
1621
|
|
package/src/server.js
CHANGED
|
@@ -123,7 +123,7 @@ export function createProxyServer(accountManager, config, hooks = {}) {
|
|
|
123
123
|
if (req.method === 'POST' && req.url === '/v1/oauth/token') {
|
|
124
124
|
const reqId = ++requestCounter;
|
|
125
125
|
const ctx = { account: '(oauth relay)', status: null };
|
|
126
|
-
const accepted = hooks.onRequestStart?.(reqId, { method: req.method, path: req.url });
|
|
126
|
+
const accepted = hooks.onRequestStart?.(reqId, { method: req.method, path: req.url, sessionKey: headerValue(req.headers, 'x-maxpool-session') });
|
|
127
127
|
if (accepted === false) {
|
|
128
128
|
res.writeHead(503, {
|
|
129
129
|
'Content-Type': 'application/json',
|
|
@@ -156,7 +156,10 @@ export function createProxyServer(accountManager, config, hooks = {}) {
|
|
|
156
156
|
|
|
157
157
|
// Track request
|
|
158
158
|
const reqId = ++requestCounter;
|
|
159
|
-
|
|
159
|
+
// sessionKey (from the per-terminal x-maxpool-session header) lets the TUI show
|
|
160
|
+
// how many distinct client sessions the in-flight requests span — so "N in-flight"
|
|
161
|
+
// isn't misread as "N sessions" (subagents of one terminal share one session key).
|
|
162
|
+
const accepted = hooks.onRequestStart?.(reqId, { method: req.method, path: req.url, sessionKey: headerValue(req.headers, 'x-maxpool-session') });
|
|
160
163
|
if (accepted === false) {
|
|
161
164
|
res.writeHead(503, {
|
|
162
165
|
'Content-Type': 'application/json',
|
|
@@ -1593,6 +1596,9 @@ function describeRequest(req, body) {
|
|
|
1593
1596
|
const origin = detectTranscriptOrigin(json);
|
|
1594
1597
|
if (origin.anthropicIncompatible) info.anthropicIncompatible = true;
|
|
1595
1598
|
if (origin.homeProvider) info.homeProvider = origin.homeProvider;
|
|
1599
|
+
// Image content (incl. tool_result-nested screenshots) keeps a request off Kimi
|
|
1600
|
+
// (Moonshot 400s on some images GLM/Anthropic accept, and a 400 is terminal).
|
|
1601
|
+
if (containsImageBlock(json.messages)) info.hasImage = true;
|
|
1596
1602
|
} catch {
|
|
1597
1603
|
// Non-JSON requests are rare; body size still gives a useful load signal.
|
|
1598
1604
|
}
|
|
@@ -1679,6 +1685,21 @@ function containsThinkingBlock(value) {
|
|
|
1679
1685
|
return false;
|
|
1680
1686
|
}
|
|
1681
1687
|
|
|
1688
|
+
// True if any message carries an `{type:'image'}` content block at ANY nesting
|
|
1689
|
+
// depth — including images nested inside a `tool_result` block (the primary
|
|
1690
|
+
// Claude Code image path: a browser/Playwright tool returning a screenshot). A
|
|
1691
|
+
// shallow 2-level scan misses those. Used to keep image requests off Kimi, whose
|
|
1692
|
+
// decoder 400s on images Anthropic/GLM accept.
|
|
1693
|
+
function containsImageBlock(value) {
|
|
1694
|
+
if (!value) return false;
|
|
1695
|
+
if (Array.isArray(value)) return value.some(containsImageBlock);
|
|
1696
|
+
if (typeof value !== 'object') return false;
|
|
1697
|
+
if (value.type === 'image') return true;
|
|
1698
|
+
if (value.content && containsImageBlock(value.content)) return true;
|
|
1699
|
+
if (value.messages && containsImageBlock(value.messages)) return true;
|
|
1700
|
+
return false;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1682
1703
|
function getMaxpoolProfile(headers) {
|
|
1683
1704
|
// headerValue() handles the x-teamclaude-* legacy fallback.
|
|
1684
1705
|
const profile = String(headerValue(headers, 'x-maxpool-profile') || 'claude').trim().toLowerCase();
|
package/src/tui.js
CHANGED
|
@@ -982,8 +982,15 @@ export class TUI {
|
|
|
982
982
|
|
|
983
983
|
// ── Activity header
|
|
984
984
|
lines.push('');
|
|
985
|
+
// "N active" reads as "N sessions" — but this is in-flight REQUESTS (Claude Code
|
|
986
|
+
// fans out many parallel subagent requests per session). Label it "in-flight" and
|
|
987
|
+
// show the distinct SESSION count (subagents of one terminal share one session key)
|
|
988
|
+
// so a busy 1-2 sessions firing dozens of requests isn't mistaken for a leak.
|
|
985
989
|
const ac = this.active.size;
|
|
986
|
-
const
|
|
990
|
+
const sessions = new Set([...this.active.values()].map(r => r.sessionKey).filter(Boolean)).size;
|
|
991
|
+
const acTag = ac > 0
|
|
992
|
+
? ` ${cyan(ac + ' in-flight')}${sessions ? dim(` · ${sessions} session${sessions === 1 ? '' : 's'}`) : ''}`
|
|
993
|
+
: '';
|
|
987
994
|
const aHdr = ` Activity${acTag} `;
|
|
988
995
|
lines.push(aHdr + dim('─'.repeat(Math.max(1, W - vw(aHdr)))));
|
|
989
996
|
|