blun-king-cli 9.1.595 → 9.1.597
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/blun.mjs +66 -8
- package/package.json +1 -1
- package/worker-host.mjs +37 -6
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:631215107f223f910482352d64f8081de5c7ebb282f9e66a53e7cd6dc93ba305
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -1536,6 +1536,7 @@ function parseExplicitMaxContextTokens(message) {
|
|
|
1536
1536
|
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
1537
1537
|
}
|
|
1538
1538
|
function isRetryableGenerateError(error) {
|
|
1539
|
+
if (error instanceof APIContextOverflowError) return false;
|
|
1539
1540
|
if (error instanceof CompactionStallError$1) return true;
|
|
1540
1541
|
if (error instanceof APIConnectionError || error instanceof APITimeoutError) return true;
|
|
1541
1542
|
if (error instanceof APIEmptyResponseError) return true;
|
|
@@ -1572,7 +1573,8 @@ function isProviderQuotaExhaustedMessage(message) {
|
|
|
1572
1573
|
return PROVIDER_QUOTA_EXHAUSTED_MESSAGE_PATTERN.test(lowerMessage) && PROVIDER_QUOTA_EXHAUSTED_CONTEXT_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1573
1574
|
}
|
|
1574
1575
|
function isContextOverflowStatusError(statusCode, message) {
|
|
1575
|
-
|
|
1576
|
+
const wrappedRejection = statusCode === 502 && /\bHTTP(?: Error)? (?:400|413|422):/i.test(message);
|
|
1577
|
+
if (statusCode !== 400 && statusCode !== 413 && statusCode !== 422 && !wrappedRejection) return false;
|
|
1576
1578
|
const lowerMessage = message.toLowerCase();
|
|
1577
1579
|
return CONTEXT_OVERFLOW_MESSAGE_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1578
1580
|
}
|
|
@@ -1998,7 +2000,8 @@ var init_fetch_http_client = __esmMin((() => {
|
|
|
1998
2000
|
const startedAt = performance.now();
|
|
1999
2001
|
try {
|
|
2000
2002
|
const response = await this.fetch(`${this.baseUrl}${pathname}`, init);
|
|
2001
|
-
const
|
|
2003
|
+
const gatewayError = response.status === 502 ? await responseError(response) : void 0;
|
|
2004
|
+
const willRetry = attempt < maxRetries && shouldRetryResponse(response) && !(gatewayError instanceof APIContextOverflowError);
|
|
2002
2005
|
notifyTransportAttempt(requestOptions?.onTransportAttempt, {
|
|
2003
2006
|
transportAttempt: attempt + 1,
|
|
2004
2007
|
...requestBytes === void 0 ? {} : { requestBytes },
|
|
@@ -2010,12 +2013,12 @@ var init_fetch_http_client = __esmMin((() => {
|
|
|
2010
2013
|
if (response.ok) return response;
|
|
2011
2014
|
if (willRetry) {
|
|
2012
2015
|
const delayMs = retryDelayMs(response.headers, attempt);
|
|
2013
|
-
await response.body?.cancel();
|
|
2016
|
+
if (gatewayError === void 0) await response.body?.cancel();
|
|
2014
2017
|
await waitForRetry(delayMs, init.signal);
|
|
2015
2018
|
attempt += 1;
|
|
2016
2019
|
continue;
|
|
2017
2020
|
}
|
|
2018
|
-
throw await responseError(response);
|
|
2021
|
+
throw gatewayError ?? await responseError(response);
|
|
2019
2022
|
} catch (error) {
|
|
2020
2023
|
if (error instanceof ChatProviderError) throw error;
|
|
2021
2024
|
const willRetry = attempt < maxRetries && init.signal?.aborted !== true && isRetryableTransportFailure(error);
|
|
@@ -2578,9 +2581,23 @@ function extractUsageFromChunk(chunk) {
|
|
|
2578
2581
|
if (choiceUsage !== null && choiceUsage !== void 0 && typeof choiceUsage === "object") return choiceUsage;
|
|
2579
2582
|
return null;
|
|
2580
2583
|
}
|
|
2584
|
+
function contextOverflowOutputCap(error, currentCap) {
|
|
2585
|
+
const maxContext = error.maxContextTokens;
|
|
2586
|
+
const counts = /requested ([\d,_]+) output tokens and your prompt contains (?:at least )?([\d,_]+) input tokens/i.exec(error.message);
|
|
2587
|
+
if (maxContext === void 0 || counts === null || !Number.isSafeInteger(maxContext) || maxContext <= 0) return;
|
|
2588
|
+
const requestedOutput = Number(counts[1].replaceAll(/[,_]/g, ""));
|
|
2589
|
+
const input = Number(counts[2].replaceAll(/[,_]/g, ""));
|
|
2590
|
+
if (!Number.isSafeInteger(input) || input < 0 || !Number.isSafeInteger(requestedOutput) || requestedOutput <= 0 || !Number.isSafeInteger(input + requestedOutput) || input + requestedOutput <= maxContext) return;
|
|
2591
|
+
const available = maxContext - input;
|
|
2592
|
+
const headroom = Math.min(1024, Math.max(1, Math.ceil(available * .01)));
|
|
2593
|
+
const cap = Math.min(requestedOutput - 1, available - headroom);
|
|
2594
|
+
if (cap < 1 || currentCap !== void 0 && (typeof currentCap !== "number" || !Number.isSafeInteger(currentCap) || cap >= currentCap)) return;
|
|
2595
|
+
return cap;
|
|
2596
|
+
}
|
|
2581
2597
|
var BLUN_TOOL_CALL_ID_POLICY, BLUN_INBOUND_REASONING_KEYS, BLUN_VISION_DATA_URL, BLUN_VISION_MAX_ATTACHMENTS, BLUN_VISION_MAX_IMAGE_BYTES, BlunStreamedMessage, BlunChatProvider;
|
|
2582
2598
|
var init_blun = __esmMin((() => {
|
|
2583
2599
|
init_blun_schema();
|
|
2600
|
+
init_errors$10();
|
|
2584
2601
|
init_blun_files();
|
|
2585
2602
|
init_chat_completions_wire();
|
|
2586
2603
|
init_chat_completions_stream();
|
|
@@ -2844,8 +2861,23 @@ var init_blun = __esmMin((() => {
|
|
|
2844
2861
|
...options.onTransportAttempt !== void 0 ? { onTransportAttempt: options.onTransportAttempt } : {}
|
|
2845
2862
|
} : void 0;
|
|
2846
2863
|
options?.onRequestSent?.();
|
|
2847
|
-
|
|
2864
|
+
let response;
|
|
2865
|
+
try {
|
|
2866
|
+
response = await client.chat.completions.create(createParams, requestOptions);
|
|
2867
|
+
} catch (error) {
|
|
2868
|
+
const rejection = normalizeFetchHttpError(error);
|
|
2869
|
+
const cap = rejection instanceof APIContextOverflowError ? contextOverflowOutputCap(rejection, createParams["max_completion_tokens"]) : void 0;
|
|
2870
|
+
if (cap === void 0) throw rejection;
|
|
2871
|
+
options?.signal?.throwIfAborted();
|
|
2872
|
+
options?.onRequestSent?.();
|
|
2873
|
+
response = await client.chat.completions.create({
|
|
2874
|
+
...createParams,
|
|
2875
|
+
max_completion_tokens: cap
|
|
2876
|
+
}, requestOptions);
|
|
2877
|
+
}
|
|
2878
|
+
return new BlunStreamedMessage(response, this._stream, reasoningRequested);
|
|
2848
2879
|
} catch (error) {
|
|
2880
|
+
if (options?.signal?.aborted === true) throw options.signal.reason ?? error;
|
|
2849
2881
|
throw normalizeFetchHttpError(error);
|
|
2850
2882
|
}
|
|
2851
2883
|
}
|
|
@@ -530546,6 +530578,7 @@ var SessionEventHandler = class {
|
|
|
530546
530578
|
currentTurnHasAssistantText = false;
|
|
530547
530579
|
currentTurnStartedAtMs;
|
|
530548
530580
|
currentTurnTokenCount;
|
|
530581
|
+
pendingChannelInterruption;
|
|
530549
530582
|
pendingModelBlockedFallback;
|
|
530550
530583
|
queuedGoalPromotionPending = false;
|
|
530551
530584
|
queuedGoalPromotionInFlight = false;
|
|
@@ -530566,6 +530599,7 @@ var SessionEventHandler = class {
|
|
|
530566
530599
|
this.currentTurnHasAssistantText = false;
|
|
530567
530600
|
this.currentTurnStartedAtMs = void 0;
|
|
530568
530601
|
this.currentTurnTokenCount = void 0;
|
|
530602
|
+
this.pendingChannelInterruption = void 0;
|
|
530569
530603
|
this.pendingModelBlockedFallback = void 0;
|
|
530570
530604
|
this.queuedGoalPromotionPending = false;
|
|
530571
530605
|
this.queuedGoalPromotionInFlight = false;
|
|
@@ -530578,6 +530612,27 @@ var SessionEventHandler = class {
|
|
|
530578
530612
|
clearAgentSwarmProgress() {
|
|
530579
530613
|
this.subAgentEventHandler.clearAgentSwarmProgress();
|
|
530580
530614
|
}
|
|
530615
|
+
async interruptForQueuedChannel() {
|
|
530616
|
+
const session = this.host.session;
|
|
530617
|
+
if (session === void 0) return;
|
|
530618
|
+
const pending = {
|
|
530619
|
+
sessionId: session.id,
|
|
530620
|
+
turnId: this.host.streamingUI.getTurnContext().turnId
|
|
530621
|
+
};
|
|
530622
|
+
this.pendingChannelInterruption = pending;
|
|
530623
|
+
try {
|
|
530624
|
+
await session.cancel();
|
|
530625
|
+
} catch (error) {
|
|
530626
|
+
if (this.pendingChannelInterruption === pending) this.pendingChannelInterruption = void 0;
|
|
530627
|
+
throw error;
|
|
530628
|
+
}
|
|
530629
|
+
}
|
|
530630
|
+
consumeChannelInterruption(sessionId, turnId) {
|
|
530631
|
+
const pending = this.pendingChannelInterruption;
|
|
530632
|
+
if (pending === void 0 || pending.sessionId !== sessionId || pending.turnId !== void 0 && pending.turnId !== String(turnId)) return false;
|
|
530633
|
+
this.pendingChannelInterruption = void 0;
|
|
530634
|
+
return true;
|
|
530635
|
+
}
|
|
530581
530636
|
hasActiveAgentSwarmToolCall() {
|
|
530582
530637
|
return this.subAgentEventHandler.hasActiveAgentSwarmToolCall();
|
|
530583
530638
|
}
|
|
@@ -530741,6 +530796,7 @@ var SessionEventHandler = class {
|
|
|
530741
530796
|
this.mcpServerStatusSpinners.clear();
|
|
530742
530797
|
}
|
|
530743
530798
|
handleTurnBegin(event) {
|
|
530799
|
+
this.pendingChannelInterruption = void 0;
|
|
530744
530800
|
this.host.goalChannelReplies?.beginTurn(event.sessionId, this.host.state.appState.goal?.goalId, event.turnId);
|
|
530745
530801
|
this.hideCompactionRetry();
|
|
530746
530802
|
const sessionId = this.host.session?.id;
|
|
@@ -530781,6 +530837,7 @@ var SessionEventHandler = class {
|
|
|
530781
530837
|
});
|
|
530782
530838
|
}
|
|
530783
530839
|
handleTurnEnd(event, sendQueued) {
|
|
530840
|
+
this.consumeChannelInterruption(event.sessionId, event.turnId);
|
|
530784
530841
|
this.host.restoreQueuedSteerAtTurnEnd(event.turnId);
|
|
530785
530842
|
const sessionId = this.host.session?.id;
|
|
530786
530843
|
if (sessionId !== void 0) finishPersonalMemoryRememberIntentTurn(sessionId, event.turnId);
|
|
@@ -530867,10 +530924,11 @@ var SessionEventHandler = class {
|
|
|
530867
530924
|
this.host.streamingUI.resetToolUi();
|
|
530868
530925
|
this.host.streamingUI.finalizeLiveTextBuffers("idle");
|
|
530869
530926
|
const reason = event.reason;
|
|
530927
|
+
const channelInterruption = this.consumeChannelInterruption(event.sessionId, event.turnId);
|
|
530870
530928
|
if (reason === "error") return;
|
|
530871
530929
|
if (reason === "aborted" || reason === void 0 || reason === "") {
|
|
530872
530930
|
this.markActiveAgentSwarmsCancelled();
|
|
530873
|
-
this.host.showStatus(uiText("sessionEvent.interrupted.user"), "error");
|
|
530931
|
+
this.host.showStatus(channelInterruption ? uiText("sessionEvent.interrupted.reason", { reason: "Telegram" }) : uiText("sessionEvent.interrupted.user"), channelInterruption ? "warning" : "error");
|
|
530874
530932
|
return;
|
|
530875
530933
|
}
|
|
530876
530934
|
this.host.showError(reason === "max_steps" ? uiText("sessionEvent.interrupted.maxSteps") : uiText("sessionEvent.interrupted.reason", { reason }));
|
|
@@ -537787,7 +537845,7 @@ var BlunTUI = class {
|
|
|
537787
537845
|
deliverOne: () => this.deliverQueuedChannelHead(),
|
|
537788
537846
|
canInterruptWaitingWork: () => this.canInterruptForQueuedChannel(),
|
|
537789
537847
|
interruptWaitingWork: async () => {
|
|
537790
|
-
await this.
|
|
537848
|
+
await this.sessionEventHandler.interruptForQueuedChannel();
|
|
537791
537849
|
}
|
|
537792
537850
|
});
|
|
537793
537851
|
this.managedQuotaWarningController = new ManagedQuotaWarningController({ onChange: (warning) => {
|
package/package.json
CHANGED
package/worker-host.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:631215107f223f910482352d64f8081de5c7ebb282f9e66a53e7cd6dc93ba305
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -1664,6 +1664,7 @@ var CompactionStallError$1 = class extends ChatProviderError {
|
|
|
1664
1664
|
}
|
|
1665
1665
|
};
|
|
1666
1666
|
function isRetryableGenerateError(error) {
|
|
1667
|
+
if (error instanceof APIContextOverflowError) return false;
|
|
1667
1668
|
if (error instanceof CompactionStallError$1) return true;
|
|
1668
1669
|
if (error instanceof APIConnectionError || error instanceof APITimeoutError) return true;
|
|
1669
1670
|
if (error instanceof APIEmptyResponseError) return true;
|
|
@@ -1728,7 +1729,8 @@ function isProviderQuotaExhaustedMessage(message) {
|
|
|
1728
1729
|
return PROVIDER_QUOTA_EXHAUSTED_MESSAGE_PATTERN.test(lowerMessage) && PROVIDER_QUOTA_EXHAUSTED_CONTEXT_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1729
1730
|
}
|
|
1730
1731
|
function isContextOverflowStatusError(statusCode, message) {
|
|
1731
|
-
|
|
1732
|
+
const wrappedRejection = statusCode === 502 && /\bHTTP(?: Error)? (?:400|413|422):/i.test(message);
|
|
1733
|
+
if (statusCode !== 400 && statusCode !== 413 && statusCode !== 422 && !wrappedRejection) return false;
|
|
1732
1734
|
const lowerMessage = message.toLowerCase();
|
|
1733
1735
|
return CONTEXT_OVERFLOW_MESSAGE_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1734
1736
|
}
|
|
@@ -1854,7 +1856,8 @@ var FetchTransport = class {
|
|
|
1854
1856
|
const startedAt = performance.now();
|
|
1855
1857
|
try {
|
|
1856
1858
|
const response = await this.fetch(`${this.baseUrl}${pathname}`, init);
|
|
1857
|
-
const
|
|
1859
|
+
const gatewayError = response.status === 502 ? await responseError(response) : void 0;
|
|
1860
|
+
const willRetry = attempt < maxRetries && shouldRetryResponse(response) && !(gatewayError instanceof APIContextOverflowError);
|
|
1858
1861
|
notifyTransportAttempt(requestOptions?.onTransportAttempt, {
|
|
1859
1862
|
transportAttempt: attempt + 1,
|
|
1860
1863
|
...requestBytes === void 0 ? {} : { requestBytes },
|
|
@@ -1866,12 +1869,12 @@ var FetchTransport = class {
|
|
|
1866
1869
|
if (response.ok) return response;
|
|
1867
1870
|
if (willRetry) {
|
|
1868
1871
|
const delayMs = retryDelayMs(response.headers, attempt);
|
|
1869
|
-
await response.body?.cancel();
|
|
1872
|
+
if (gatewayError === void 0) await response.body?.cancel();
|
|
1870
1873
|
await waitForRetry(delayMs, init.signal);
|
|
1871
1874
|
attempt += 1;
|
|
1872
1875
|
continue;
|
|
1873
1876
|
}
|
|
1874
|
-
throw await responseError(response);
|
|
1877
|
+
throw gatewayError ?? await responseError(response);
|
|
1875
1878
|
} catch (error) {
|
|
1876
1879
|
if (error instanceof ChatProviderError) throw error;
|
|
1877
1880
|
const willRetry = attempt < maxRetries && init.signal?.aborted !== true && isRetryableTransportFailure(error);
|
|
@@ -2698,6 +2701,19 @@ var BlunStreamedMessage = class {
|
|
|
2698
2701
|
}
|
|
2699
2702
|
}
|
|
2700
2703
|
};
|
|
2704
|
+
function contextOverflowOutputCap(error, currentCap) {
|
|
2705
|
+
const maxContext = error.maxContextTokens;
|
|
2706
|
+
const counts = /requested ([\d,_]+) output tokens and your prompt contains (?:at least )?([\d,_]+) input tokens/i.exec(error.message);
|
|
2707
|
+
if (maxContext === void 0 || counts === null || !Number.isSafeInteger(maxContext) || maxContext <= 0) return;
|
|
2708
|
+
const requestedOutput = Number(counts[1].replaceAll(/[,_]/g, ""));
|
|
2709
|
+
const input = Number(counts[2].replaceAll(/[,_]/g, ""));
|
|
2710
|
+
if (!Number.isSafeInteger(input) || input < 0 || !Number.isSafeInteger(requestedOutput) || requestedOutput <= 0 || !Number.isSafeInteger(input + requestedOutput) || input + requestedOutput <= maxContext) return;
|
|
2711
|
+
const available = maxContext - input;
|
|
2712
|
+
const headroom = Math.min(1024, Math.max(1, Math.ceil(available * .01)));
|
|
2713
|
+
const cap = Math.min(requestedOutput - 1, available - headroom);
|
|
2714
|
+
if (cap < 1 || currentCap !== void 0 && (typeof currentCap !== "number" || !Number.isSafeInteger(currentCap) || cap >= currentCap)) return;
|
|
2715
|
+
return cap;
|
|
2716
|
+
}
|
|
2701
2717
|
var BlunChatProvider = class {
|
|
2702
2718
|
name = "blun";
|
|
2703
2719
|
_model;
|
|
@@ -2852,8 +2868,23 @@ var BlunChatProvider = class {
|
|
|
2852
2868
|
...options.onTransportAttempt !== void 0 ? { onTransportAttempt: options.onTransportAttempt } : {}
|
|
2853
2869
|
} : void 0;
|
|
2854
2870
|
options?.onRequestSent?.();
|
|
2855
|
-
|
|
2871
|
+
let response;
|
|
2872
|
+
try {
|
|
2873
|
+
response = await client.chat.completions.create(createParams, requestOptions);
|
|
2874
|
+
} catch (error) {
|
|
2875
|
+
const rejection = normalizeFetchHttpError(error);
|
|
2876
|
+
const cap = rejection instanceof APIContextOverflowError ? contextOverflowOutputCap(rejection, createParams["max_completion_tokens"]) : void 0;
|
|
2877
|
+
if (cap === void 0) throw rejection;
|
|
2878
|
+
options?.signal?.throwIfAborted();
|
|
2879
|
+
options?.onRequestSent?.();
|
|
2880
|
+
response = await client.chat.completions.create({
|
|
2881
|
+
...createParams,
|
|
2882
|
+
max_completion_tokens: cap
|
|
2883
|
+
}, requestOptions);
|
|
2884
|
+
}
|
|
2885
|
+
return new BlunStreamedMessage(response, this._stream, reasoningRequested);
|
|
2856
2886
|
} catch (error) {
|
|
2887
|
+
if (options?.signal?.aborted === true) throw options.signal.reason ?? error;
|
|
2857
2888
|
throw normalizeFetchHttpError(error);
|
|
2858
2889
|
}
|
|
2859
2890
|
}
|