blun-king-cli 9.1.375 → 9.1.377

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.
@@ -236,26 +236,13 @@ function selectHistoricalToolResultOffloads(textLengths) {
236
236
  const normalized = textLengths.map((length) => (
237
237
  Number.isFinite(length) && length > 0 ? Math.floor(length) : 0
238
238
  ));
239
- const totalChars = normalized.reduce((total, length) => total + length, 0);
240
- if (totalChars <= TOOL_RESULT_HISTORICAL_MAX_CHARS) return [];
241
-
242
- let projectedChars = totalChars;
243
- const selected = [];
244
- const candidates = normalized
239
+ return normalized
245
240
  .map((length, index) => ({ index, length }))
246
241
  .filter(({ length }) => (
247
242
  length >= TOOL_RESULT_HISTORICAL_MIN_ITEM_CHARS
248
243
  && length > TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS
249
244
  ))
250
- .sort((left, right) => right.length - left.length || left.index - right.index);
251
-
252
- for (const candidate of candidates) {
253
- if (projectedChars <= TOOL_RESULT_HISTORICAL_MAX_CHARS) break;
254
- projectedChars -= candidate.length - TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS;
255
- selected.push(candidate.index);
256
- }
257
-
258
- return selected.sort((left, right) => left - right);
245
+ .map(({ index }) => index);
259
246
  }
260
247
 
261
248
  module.exports = {
package/blun.mjs CHANGED
@@ -262334,6 +262334,7 @@ var init_turn = __esmMin((() => {
262334
262334
  hooks: {
262335
262335
  beforeStep: async ({ signal: stepSignal, stepNumber }) => {
262336
262336
  await this.agent.records.flush();
262337
+ await this.agent.toolResultBatchOffload.detect();
262337
262338
  this.agent.microCompaction.detect();
262338
262339
  await this.agent.userMessageOffload.detect();
262339
262340
  await this.agent.assistantMessageOffload.detect();
@@ -419328,6 +419329,8 @@ const OWNERSHIP_SETTLE_MS = 50;
419328
419329
  const OWNERSHIP_HANDOFF_WARNING_MS = 5e3;
419329
419330
  const BRIDGE_STOP_TIMEOUT_MS = 2500;
419330
419331
  const BRIDGE_FORCE_STOP_TIMEOUT_MS = 500;
419332
+ const CHANNEL_STEER_CONFIRM_TIMEOUT_MS = 15e3;
419333
+ const CHANNEL_DELIVERY_MAX_FAILURES = 3;
419331
419334
  const BLUN_NODE_FALLBACK_SUBCOMMAND = "__plugin_run_node";
419332
419335
  function isBlunNativeBinary(execPath) {
419333
419336
  return !basename(execPath).toLowerCase().startsWith("node");
@@ -517295,9 +517298,16 @@ var BlunTUI = class {
517295
517298
  try {
517296
517299
  const result = await this.harness.withInteractiveAgent(item.agentId ?? "main", () => session.steerActive(input, expectedTurnId === void 0 ? {} : { expectedTurnId }));
517297
517300
  if (!result.accepted) return this.recoverRejectedActiveSteer(inFlight);
517301
+ inFlight.turnId = String(result.turnId);
517298
517302
  inFlight.accepted = true;
517299
517303
  if (result.duplicate === true) return this.commitQueuedSteer(inFlight);
517300
517304
  if (inFlight.turnEnded) return restoreHead();
517305
+ if (!inFlight.stepStarted) {
517306
+ inFlight.confirmationTimer = setTimeout(() => {
517307
+ if (this.queueSteerInFlight === inFlight && inFlight.accepted && !inFlight.stepStarted) restoreHead(new Error("channel steer confirmation timed out"));
517308
+ }, CHANNEL_STEER_CONFIRM_TIMEOUT_MS);
517309
+ inFlight.confirmationTimer.unref?.();
517310
+ }
517301
517311
  this.commitQueuedSteerIfReady(inFlight);
517302
517312
  } catch (error) {
517303
517313
  return restoreHead(error);
@@ -517340,6 +517350,7 @@ var BlunTUI = class {
517340
517350
  }
517341
517351
  commitQueuedSteer(inFlight) {
517342
517352
  if (this.queueSteerInFlight !== inFlight) return;
517353
+ if (inFlight.confirmationTimer !== void 0) clearTimeout(inFlight.confirmationTimer);
517343
517354
  this.queueSteerInFlight = void 0;
517344
517355
  inFlight.onCommit();
517345
517356
  this.updateQueueDisplay();
@@ -517356,11 +517367,64 @@ var BlunTUI = class {
517356
517367
  }
517357
517368
  return restored;
517358
517369
  }
517370
+ quarantineQueuedSteer(inFlight, error) {
517371
+ if (this.queueSteerInFlight !== inFlight) return false;
517372
+ if (inFlight.confirmationTimer !== void 0) clearTimeout(inFlight.confirmationTimer);
517373
+ this.queueSteerInFlight = void 0;
517374
+ inFlight.onRestore?.();
517375
+ const record = {
517376
+ version: 1,
517377
+ quarantinedAt: new Date().toISOString(),
517378
+ reason: String(error?.code ?? error?.name ?? "channel_delivery_failed"),
517379
+ attempts: CHANNEL_DELIVERY_MAX_FAILURES,
517380
+ items: inFlight.items.map((item) => ({
517381
+ text: item.text,
517382
+ displayText: item.displayText,
517383
+ origin: item.origin,
517384
+ mode: item.mode,
517385
+ agentId: item.agentId,
517386
+ chatId: item.channelChatId,
517387
+ queueKey: item.queueKey,
517388
+ contextOnly: item.channelContextOnly === true,
517389
+ attention: item.channelAttention === true,
517390
+ urgent: item.channelUrgent === true,
517391
+ direct: item.channelDirect === true,
517392
+ addressed: item.channelAddressed === true,
517393
+ imagePath: item.channelImagePath
517394
+ }))
517395
+ };
517396
+ try {
517397
+ appendFileSync(join(telegramStateDir(), "inbound-queue-quarantine.jsonl"), `${JSON.stringify(record)}\n`, { encoding: "utf8", mode: 384 });
517398
+ } catch (archiveError) {
517399
+ this.state.queuedMessages = [...inFlight.items.map((item) => ({
517400
+ ...item,
517401
+ channelDeliveryFailures: CHANNEL_DELIVERY_MAX_FAILURES - 1
517402
+ })), ...this.state.queuedMessages];
517403
+ this.showError(uiText("blunTui.steer.failed", { error: formatErrorMessage$2(archiveError) }));
517404
+ this.updateQueueDisplay();
517405
+ this.state.ui.requestRender();
517406
+ this.scheduleQueueDrain();
517407
+ return false;
517408
+ }
517409
+ for (const item of inFlight.items) item.channelAcknowledge?.();
517410
+ if (this.queueFlushBatchRemaining > 0) this.queueFlushBatchRemaining = Math.max(0, this.queueFlushBatchRemaining - inFlight.items.length);
517411
+ this.track("channel_queue_quarantined", { count: inFlight.items.length, attempts: CHANNEL_DELIVERY_MAX_FAILURES });
517412
+ this.updateQueueDisplay();
517413
+ this.state.ui.requestRender();
517414
+ this.scheduleQueueDrain();
517415
+ return false;
517416
+ }
517359
517417
  restoreQueuedSteer(inFlight, error) {
517360
517418
  if (this.queueSteerInFlight !== inFlight) return false;
517419
+ if (inFlight.confirmationTimer !== void 0) clearTimeout(inFlight.confirmationTimer);
517420
+ const failureCount = Math.max(0, ...inFlight.items.map((item) => Number(item.channelDeliveryFailures) || 0)) + 1;
517421
+ if (failureCount >= CHANNEL_DELIVERY_MAX_FAILURES) return this.quarantineQueuedSteer(inFlight, error);
517361
517422
  this.queueSteerInFlight = void 0;
517362
517423
  inFlight.onRestore?.();
517363
- this.state.queuedMessages = [...inFlight.items, ...this.state.queuedMessages];
517424
+ this.state.queuedMessages = [...inFlight.items.map((item) => ({
517425
+ ...item,
517426
+ channelDeliveryFailures: failureCount
517427
+ })), ...this.state.queuedMessages];
517364
517428
  if (error !== void 0) this.showError(uiText("blunTui.steer.failed", { error: formatErrorMessage$2(error) }));
517365
517429
  this.updateQueueDisplay();
517366
517430
  this.state.ui.requestRender();
@@ -517436,7 +517500,7 @@ var BlunTUI = class {
517436
517500
  for (const item of items) this.appendTranscriptEntry({
517437
517501
  id: nextTranscriptId(),
517438
517502
  kind: "user",
517439
- turnId,
517503
+ turnId: inFlight.turnId,
517440
517504
  renderMode: "plain",
517441
517505
  content: item.text.trim()
517442
517506
  });
@@ -517448,6 +517512,7 @@ var BlunTUI = class {
517448
517512
  if (this.queueSteerInFlight !== inFlight) return;
517449
517513
  if (!result.accepted) this.recoverRejectedActiveSteer(inFlight);
517450
517514
  else {
517515
+ inFlight.turnId = String(result.turnId);
517451
517516
  inFlight.accepted = true;
517452
517517
  if (inFlight.turnEnded) this.restoreQueuedSteer(inFlight);
517453
517518
  else this.commitQueuedSteerIfReady(inFlight);
@@ -517634,6 +517699,10 @@ var BlunTUI = class {
517634
517699
  this.state.ui.requestRender();
517635
517700
  return;
517636
517701
  }
517702
+ if (command.name === "loop" && activeTurn && !this.queueCommandRunning) {
517703
+ this.runTelegramRemoteCommand(item);
517704
+ return;
517705
+ }
517637
517706
  const busy = this.session === void 0 || this.state.appState.model.trim().length === 0 || this.state.queuedMessages.length > 0 || this.queueSteerInFlight !== void 0 || this.pendingChannelReplyGuard !== void 0 || this.deferUserMessages || this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle" || this.state.appState.isCompacting;
517638
517707
  if (busy) {
517639
517708
  this.state.queuedMessages.push(item);
@@ -517670,7 +517739,8 @@ var BlunTUI = class {
517670
517739
  if (this.telegramRemoteCommandContext === context) this.telegramRemoteCommandContext = void 0;
517671
517740
  if (!context.sentModelTurn) {
517672
517741
  const response = context.responses.at(-1) ?? item.displayText ?? item.text;
517673
- if (await sendReplyFallback(item.channelChatId, response, false)) item.channelAcknowledge?.();
517742
+ if (!await sendReplyFallback(item.channelChatId, response, false)) this.track("telegram_command_reply_failed", { command: item.telegramCommandName });
517743
+ item.channelAcknowledge?.();
517674
517744
  }
517675
517745
  this.queueCommandRunning = false;
517676
517746
  if (!this.editorReplacementActive) this.preserveQueueAcrossSessionReset = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.375",
3
+ "version": "9.1.377",
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": {