blun-king-cli 9.1.285 → 9.1.287
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.
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MAX_MODEL_RETRY_HINT_CHARS = 32;
|
|
4
|
+
const MAX_MODEL_RETRY_ATTEMPTS = 99;
|
|
5
|
+
const MAX_MODEL_RETRY_DELAY_MS = 600_000;
|
|
6
|
+
|
|
7
|
+
function boundedInteger(value, minimum, maximum, fallback) {
|
|
8
|
+
if (!Number.isFinite(value)) return fallback;
|
|
9
|
+
return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function formatRetryDelay(delayMs) {
|
|
13
|
+
const bounded = boundedInteger(delayMs, 0, MAX_MODEL_RETRY_DELAY_MS, 0);
|
|
14
|
+
if (bounded === 0) return '';
|
|
15
|
+
if (bounded < 1_000) return `${bounded}ms`;
|
|
16
|
+
return `${Math.ceil(bounded / 100) / 10}s`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function formatModelRetryProgress(event = {}) {
|
|
20
|
+
const maxAttempts = boundedInteger(
|
|
21
|
+
event.maxAttempts,
|
|
22
|
+
1,
|
|
23
|
+
MAX_MODEL_RETRY_ATTEMPTS,
|
|
24
|
+
1,
|
|
25
|
+
);
|
|
26
|
+
const failedAttempt = boundedInteger(
|
|
27
|
+
event.failedAttempt,
|
|
28
|
+
0,
|
|
29
|
+
maxAttempts - 1,
|
|
30
|
+
0,
|
|
31
|
+
);
|
|
32
|
+
const nextAttempt = boundedInteger(
|
|
33
|
+
event.nextAttempt,
|
|
34
|
+
1,
|
|
35
|
+
maxAttempts,
|
|
36
|
+
Math.min(maxAttempts, failedAttempt + 1),
|
|
37
|
+
);
|
|
38
|
+
const delay = formatRetryDelay(event.delayMs);
|
|
39
|
+
const hint = `Retry ${nextAttempt}/${maxAttempts}${delay ? ` | ${delay}` : ''}`;
|
|
40
|
+
return hint.slice(0, MAX_MODEL_RETRY_HINT_CHARS);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = {
|
|
44
|
+
MAX_MODEL_RETRY_HINT_CHARS,
|
|
45
|
+
formatModelRetryProgress,
|
|
46
|
+
};
|
|
@@ -4,6 +4,7 @@ const TOOL_SCHEMA_BUDGET_RATIO = 0.25;
|
|
|
4
4
|
const TOOL_SCHEMA_MAX_TOKENS = 32_000;
|
|
5
5
|
const DEFERRED_TOOL_LOADER_NAME = 'ToolSearch';
|
|
6
6
|
const MAX_PERSISTENT_DEFERRED_TOOLS = 4;
|
|
7
|
+
const MAX_TOOL_SEARCH_QUERY_CHARS = 1_000;
|
|
7
8
|
const TOOL_SEARCH_INTENT_WORDS = new Set([
|
|
8
9
|
'find', 'fetch', 'get', 'holen', 'list', 'read', 'search', 'show', 'anzeigen', 'lesen', 'suchen',
|
|
9
10
|
]);
|
|
@@ -83,8 +84,18 @@ function deferredToolCatalog(tools) {
|
|
|
83
84
|
.sort((left, right) => left.localeCompare(right));
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
function normalizeDeferredToolQuery(value) {
|
|
88
|
+
const query = String(value ?? '').trim();
|
|
89
|
+
if (query.length <= MAX_TOOL_SEARCH_QUERY_CHARS) return query;
|
|
90
|
+
const bounded = query.slice(0, MAX_TOOL_SEARCH_QUERY_CHARS);
|
|
91
|
+
const wordBoundary = bounded.lastIndexOf(' ');
|
|
92
|
+
return (wordBoundary >= MAX_TOOL_SEARCH_QUERY_CHARS * 0.8
|
|
93
|
+
? bounded.slice(0, wordBoundary)
|
|
94
|
+
: bounded).trimEnd();
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
function searchDeferredTools(tools, query) {
|
|
87
|
-
const normalized =
|
|
98
|
+
const normalized = normalizeDeferredToolQuery(query).toLowerCase();
|
|
88
99
|
if (!normalized) return [];
|
|
89
100
|
if (normalized.startsWith('select:')) {
|
|
90
101
|
const selector = normalized.slice('select:'.length).trim();
|
|
@@ -132,7 +143,7 @@ function relatedSearchTerms(token) {
|
|
|
132
143
|
}
|
|
133
144
|
|
|
134
145
|
function searchRelatedDeferredTools(tools, query, options = {}) {
|
|
135
|
-
const normalized =
|
|
146
|
+
const normalized = normalizeDeferredToolQuery(query).toLowerCase();
|
|
136
147
|
if (!normalized || normalized.startsWith('select:')) return [];
|
|
137
148
|
const tokens = normalized.split(/\s+/).filter(Boolean);
|
|
138
149
|
const requestedNameTokens = tokens
|
|
@@ -230,6 +241,7 @@ function createDeferredToolLoader(selectedTools, deferredTools, loadedToolNames
|
|
|
230
241
|
properties: {
|
|
231
242
|
query: {
|
|
232
243
|
type: 'string',
|
|
244
|
+
maxLength: MAX_TOOL_SEARCH_QUERY_CHARS,
|
|
233
245
|
description: 'Exact selection or keyword query, for example select:download_attachment or +slack send.',
|
|
234
246
|
},
|
|
235
247
|
},
|
|
@@ -237,7 +249,7 @@ function createDeferredToolLoader(selectedTools, deferredTools, loadedToolNames
|
|
|
237
249
|
additionalProperties: false,
|
|
238
250
|
},
|
|
239
251
|
resolveExecution(args) {
|
|
240
|
-
const query =
|
|
252
|
+
const query = normalizeDeferredToolQuery(args?.query);
|
|
241
253
|
return {
|
|
242
254
|
description: query ? `Searching tool schemas for ${query}` : 'Searching tool schemas',
|
|
243
255
|
approvalRule: DEFERRED_TOOL_LOADER_NAME,
|
|
@@ -302,12 +314,14 @@ module.exports = {
|
|
|
302
314
|
CORE_TOOL_NAMES,
|
|
303
315
|
DEFERRED_TOOL_LOADER_NAME,
|
|
304
316
|
MAX_PERSISTENT_DEFERRED_TOOLS,
|
|
317
|
+
MAX_TOOL_SEARCH_QUERY_CHARS,
|
|
305
318
|
TOOL_SCHEMA_BUDGET_RATIO,
|
|
306
319
|
TOOL_SCHEMA_MAX_TOKENS,
|
|
307
320
|
createDeferredToolLoader,
|
|
308
321
|
deferredToolCatalog,
|
|
309
322
|
deferredToolNames,
|
|
310
323
|
mediaGenerationToolNamesForText,
|
|
324
|
+
normalizeDeferredToolQuery,
|
|
311
325
|
rememberDeferredToolAfterNotFound,
|
|
312
326
|
toolSchemaBudgetTokens,
|
|
313
327
|
};
|
package/blun.mjs
CHANGED
|
@@ -507180,6 +507180,7 @@ function normalizeJson(value) {
|
|
|
507180
507180
|
}
|
|
507181
507181
|
//#endregion
|
|
507182
507182
|
//#region src/tui/controllers/session-event-handler.ts
|
|
507183
|
+
var { formatModelRetryProgress } = createRequire(import.meta.url)("./bin/model-retry-progress-policy.cjs");
|
|
507183
507184
|
const MANAGED_TELEGRAM_MCP_SERVER = "plugin-telegram:telegram";
|
|
507184
507185
|
function isManagedTelegramMissingTokenFailure(server) {
|
|
507185
507186
|
return server.name === MANAGED_TELEGRAM_MCP_SERVER && server.status === "failed" && server.error?.includes("BLUN_TELEGRAM_BOT_TOKEN required") === true;
|
|
@@ -507220,7 +507221,9 @@ var SessionEventHandler = class {
|
|
|
507220
507221
|
queuedGoalPromotionInFlight = false;
|
|
507221
507222
|
queuedGoalPromotionTimer;
|
|
507222
507223
|
lastCompactionInstruction;
|
|
507224
|
+
modelRetryHint;
|
|
507223
507225
|
resetRuntimeState() {
|
|
507226
|
+
this.clearModelRetryHint();
|
|
507224
507227
|
this.turnWatchdog.stop();
|
|
507225
507228
|
this.backgroundTasks.clear();
|
|
507226
507229
|
this.backgroundTaskTranscriptedTerminal.clear();
|
|
@@ -507320,7 +507323,9 @@ var SessionEventHandler = class {
|
|
|
507320
507323
|
this.handleStepCompleted(event);
|
|
507321
507324
|
this.host.releaseChannelQueueAtSafePoint();
|
|
507322
507325
|
break;
|
|
507323
|
-
case "turn.step.retrying":
|
|
507326
|
+
case "turn.step.retrying":
|
|
507327
|
+
this.handleStepRetrying(event);
|
|
507328
|
+
break;
|
|
507324
507329
|
case "tool.progress":
|
|
507325
507330
|
this.handleToolProgress(event);
|
|
507326
507331
|
break;
|
|
@@ -507409,6 +507414,7 @@ var SessionEventHandler = class {
|
|
|
507409
507414
|
this.mcpServerStatusSpinners.clear();
|
|
507410
507415
|
}
|
|
507411
507416
|
handleTurnBegin(event) {
|
|
507417
|
+
this.clearModelRetryHint();
|
|
507412
507418
|
this.turnWatchdog.start();
|
|
507413
507419
|
const sessionId = this.host.session?.id;
|
|
507414
507420
|
if (sessionId !== void 0) bindPersonalMemoryRememberIntentTurn(sessionId, event.turnId);
|
|
@@ -507451,6 +507457,7 @@ var SessionEventHandler = class {
|
|
|
507451
507457
|
}, 0);
|
|
507452
507458
|
}
|
|
507453
507459
|
handleTurnEnd(event, sendQueued) {
|
|
507460
|
+
this.clearModelRetryHint();
|
|
507454
507461
|
this.turnWatchdog.stop();
|
|
507455
507462
|
this.host.restoreQueuedSteerAtTurnEnd(event.turnId);
|
|
507456
507463
|
const sessionId = this.host.session?.id;
|
|
@@ -507477,6 +507484,7 @@ var SessionEventHandler = class {
|
|
|
507477
507484
|
}
|
|
507478
507485
|
handleStepBegin(event) {
|
|
507479
507486
|
this.turnWatchdog.recordProgress();
|
|
507487
|
+
this.clearModelRetryHint();
|
|
507480
507488
|
this.host.commitQueuedSteerAtStepStart(event.turnId);
|
|
507481
507489
|
this.host.streamingUI.flushNow();
|
|
507482
507490
|
this.host.streamingUI.setStep(event.step);
|
|
@@ -507493,6 +507501,7 @@ var SessionEventHandler = class {
|
|
|
507493
507501
|
});
|
|
507494
507502
|
}
|
|
507495
507503
|
handleStepCompleted(event) {
|
|
507504
|
+
this.clearModelRetryHint();
|
|
507496
507505
|
this.host.streamingUI.flushNow();
|
|
507497
507506
|
if (event.usage !== void 0) this.currentTurnTokenCount = (this.currentTurnTokenCount ?? 0) + totalTokenUsage(event.usage);
|
|
507498
507507
|
this.maybeShowDebugTiming(event);
|
|
@@ -507535,6 +507544,7 @@ var SessionEventHandler = class {
|
|
|
507535
507544
|
this.subAgentEventHandler.markActiveAgentSwarmsCancelled();
|
|
507536
507545
|
}
|
|
507537
507546
|
handleStepInterrupted(event) {
|
|
507547
|
+
this.clearModelRetryHint();
|
|
507538
507548
|
this.host.streamingUI.flushNow();
|
|
507539
507549
|
this.host.streamingUI.resetToolUi();
|
|
507540
507550
|
this.host.streamingUI.finalizeLiveTextBuffers("idle");
|
|
@@ -507547,10 +507557,26 @@ var SessionEventHandler = class {
|
|
|
507547
507557
|
}
|
|
507548
507558
|
this.host.showError(reason === "max_steps" ? uiText("sessionEvent.interrupted.maxSteps") : uiText("sessionEvent.interrupted.reason", { reason }));
|
|
507549
507559
|
}
|
|
507560
|
+
handleStepRetrying(event) {
|
|
507561
|
+
this.turnWatchdog.recordProgress();
|
|
507562
|
+
const hint = formatModelRetryProgress(event);
|
|
507563
|
+
this.modelRetryHint = hint;
|
|
507564
|
+
this.host.state.footer.setTransientHint(hint);
|
|
507565
|
+
this.host.state.ui.requestRender();
|
|
507566
|
+
}
|
|
507567
|
+
clearModelRetryHint() {
|
|
507568
|
+
if (this.modelRetryHint === void 0) return;
|
|
507569
|
+
if (this.host.state.footer.getTransientHint() === this.modelRetryHint) {
|
|
507570
|
+
this.host.state.footer.setTransientHint(null);
|
|
507571
|
+
this.host.state.ui.requestRender();
|
|
507572
|
+
}
|
|
507573
|
+
this.modelRetryHint = void 0;
|
|
507574
|
+
}
|
|
507550
507575
|
handleThinkingDelta(event) {
|
|
507551
507576
|
const { state, streamingUI } = this.host;
|
|
507552
507577
|
if (event.delta.length === 0 && !streamingUI.hasThinkingDraft()) return;
|
|
507553
507578
|
if (event.delta.length > 0) this.turnWatchdog.recordProgress();
|
|
507579
|
+
if (event.delta.length > 0) this.clearModelRetryHint();
|
|
507554
507580
|
streamingUI.appendThinkingDelta(event.delta);
|
|
507555
507581
|
this.host.patchLivePane({ mode: "idle" });
|
|
507556
507582
|
if (state.appState.streamingPhase !== "thinking") this.host.setAppState({
|
|
@@ -507564,6 +507590,7 @@ var SessionEventHandler = class {
|
|
|
507564
507590
|
if (streamingUI.hasThinkingDraft()) streamingUI.flushThinkingToTranscript("idle");
|
|
507565
507591
|
if (event.delta.trim().length > 0) {
|
|
507566
507592
|
this.turnWatchdog.recordProgress();
|
|
507593
|
+
this.clearModelRetryHint();
|
|
507567
507594
|
this.currentTurnHasAssistantText = true;
|
|
507568
507595
|
this.pendingModelBlockedFallback = void 0;
|
|
507569
507596
|
}
|
|
@@ -507601,6 +507628,7 @@ var SessionEventHandler = class {
|
|
|
507601
507628
|
});
|
|
507602
507629
|
}
|
|
507603
507630
|
handleToolCall(event) {
|
|
507631
|
+
this.clearModelRetryHint();
|
|
507604
507632
|
this.turnWatchdog.recordToolCall(event.toolCallId, event.name, event.args);
|
|
507605
507633
|
const { streamingUI } = this.host;
|
|
507606
507634
|
streamingUI.flushNow();
|