blun-king-cli 9.1.285 → 9.1.286

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
+ };
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": break;
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.285",
3
+ "version": "9.1.286",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {