blun-king-cli 9.1.45 → 9.1.47

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/LIESMICH.txt CHANGED
@@ -9,7 +9,7 @@ Installation
9
9
  ------------
10
10
  Die geprüfte Version exakt global installieren:
11
11
 
12
- npm install -g blun-king-cli@9.1.45
12
+ npm install -g blun-king-cli@9.1.47
13
13
 
14
14
  Start
15
15
  -----
package/README.md CHANGED
@@ -9,7 +9,7 @@ Voraussetzung ist Node.js 24.15 oder neuer. Die geprüfte Version wird exakt
9
9
  installiert:
10
10
 
11
11
  ```powershell
12
- npm install -g blun-king-cli@9.1.45
12
+ npm install -g blun-king-cli@9.1.47
13
13
  ```
14
14
 
15
15
  ## Reproduzierbares Staging und Packen
package/blun.mjs CHANGED
@@ -75557,6 +75557,9 @@ var init_full = __esmMin((() => {
75557
75557
  const estimatedProgressPercent = estimateCompactionProgressPercent(stage, estimatedStageCount);
75558
75558
  const windowUsagePercent = estimateCompactionWindowUsagePercent(estimatedCompactionRequestTokens, compactionRequestLimit);
75559
75559
  this.agent.log.info("compaction stage request", {
75560
+ requestPurpose: "compaction",
75561
+ toolSuppressionReason: "compaction_summary",
75562
+ selectedToolCount: compactionTools.length,
75560
75563
  source: data.source,
75561
75564
  stage,
75562
75565
  estimatedStageCount,
@@ -76582,6 +76585,24 @@ var init_jitter = __esmMin((() => {
76582
76585
  }));
76583
76586
  //#endregion
76584
76587
  //#region ../../packages/agent-core/src/tools/cron/scheduler.ts
76588
+ function sessionLoopIntervalMs(task) {
76589
+ if (task.owner !== "session-loop" || typeof task.loopInterval !== "string") return null;
76590
+ if (task.loopInterval === "auto") return 15 * 6e4;
76591
+ const match = /^([1-9]\d*)(m|h|d)$/i.exec(task.loopInterval);
76592
+ if (match === null) return null;
76593
+ const amount = Number(match[1]);
76594
+ const unit = match[2]?.toLowerCase();
76595
+ const multiplier = unit === "m" ? 6e4 : unit === "h" ? 36e5 : 864e5;
76596
+ const intervalMs = amount * multiplier;
76597
+ return Number.isSafeInteger(intervalMs) ? intervalMs : null;
76598
+ }
76599
+ function countSessionLoopCoalesced(intervalMs, firstFireMs, nowMs) {
76600
+ const count = Math.max(1, Math.min(MAX_COALESCE_ITERATIONS, Math.floor((nowMs - firstFireMs) / intervalMs) + 1));
76601
+ return {
76602
+ count,
76603
+ lastDueMs: firstFireMs + (count - 1) * intervalMs
76604
+ };
76605
+ }
76585
76606
  function createCronScheduler(opts) {
76586
76607
  const { clocks, source, onFire, isIdle, isKilled, removeOneShot, onAdvanceCursor, pollIntervalMs } = opts;
76587
76608
  const parsedCache = /* @__PURE__ */ new Map();
@@ -76605,6 +76626,8 @@ function createCronScheduler(opts) {
76605
76626
  * the search budget (legal-but-never-fires expression).
76606
76627
  */
76607
76628
  function computeJitteredNext(task, parsed, baseMs) {
76629
+ const intervalMs = sessionLoopIntervalMs(task);
76630
+ if (intervalMs !== null) return baseMs + intervalMs;
76608
76631
  const ideal = computeNextCronRun(parsed, baseMs);
76609
76632
  if (ideal === null) return null;
76610
76633
  if (task.recurring === false) return oneShotJitteredNextCronRunMs(task, ideal);
@@ -76668,11 +76691,12 @@ function createCronScheduler(opts) {
76668
76691
  const nextFireAt = computeJitteredNext(task, parsed, baseFromMs);
76669
76692
  if (nextFireAt === null) continue;
76670
76693
  if (now < nextFireAt) continue;
76671
- const ideal = computeNextCronRun(parsed, baseFromMs);
76694
+ const intervalMs = sessionLoopIntervalMs(task);
76695
+ const ideal = intervalMs === null ? computeNextCronRun(parsed, baseFromMs) : nextFireAt;
76672
76696
  let coalescedCount = 1;
76673
76697
  let lastDueMs = null;
76674
76698
  if (task.recurring !== false && ideal !== null) {
76675
- const result = countCoalesced(task, parsed, ideal, now);
76699
+ const result = intervalMs === null ? countCoalesced(task, parsed, ideal, now) : countSessionLoopCoalesced(intervalMs, ideal, now);
76676
76700
  coalescedCount = Math.max(1, result.count);
76677
76701
  lastDueMs = result.lastDueMs;
76678
76702
  }
@@ -77632,6 +77656,10 @@ var init_cron_create = __esmMin((() => {
77632
77656
  //#endregion
77633
77657
  //#region ../../packages/agent-core/src/agent/session-loop.ts
77634
77658
  function parseLoopInterval(rawInterval) {
77659
+ if (rawInterval.trim().toLowerCase() === "auto") return {
77660
+ interval: "auto",
77661
+ cron: "* * * * *"
77662
+ };
77635
77663
  const match = LOOP_INTERVAL_PATTERN.exec(rawInterval.trim());
77636
77664
  if (match === null) throw invalidLoopInterval(rawInterval);
77637
77665
  const amount = Number(match[1]);
@@ -77639,25 +77667,13 @@ function parseLoopInterval(rawInterval) {
77639
77667
  if (!Number.isSafeInteger(amount)) throw invalidLoopInterval(rawInterval);
77640
77668
  const totalMinutes = unit === "m" ? amount : unit === "h" ? amount * 60 : amount * 1440;
77641
77669
  if (!Number.isSafeInteger(totalMinutes)) throw invalidLoopInterval(rawInterval);
77642
- if (totalMinutes === 1440) return {
77643
- interval: "1d",
77644
- cron: "0 0 * * *"
77645
- };
77646
- if (totalMinutes < 60 && 60 % totalMinutes === 0) return {
77647
- interval: `${String(totalMinutes)}m`,
77648
- cron: totalMinutes === 1 ? "* * * * *" : `*/${String(totalMinutes)} * * * *`
77670
+ return {
77671
+ interval: `${String(amount)}${unit}`,
77672
+ cron: "* * * * *"
77649
77673
  };
77650
- if (totalMinutes < 1440 && totalMinutes % 60 === 0) {
77651
- const hours = totalMinutes / 60;
77652
- if (24 % hours === 0) return {
77653
- interval: `${String(hours)}h`,
77654
- cron: hours === 1 ? "0 * * * *" : `0 */${String(hours)} * * *`
77655
- };
77656
- }
77657
- throw invalidLoopInterval(rawInterval);
77658
77674
  }
77659
77675
  function invalidLoopInterval(rawInterval) {
77660
- return new BlunError(ErrorCodes.LOOP_INTERVAL_INVALID, `Invalid loop interval ${JSON.stringify(rawInterval)}; use an exact cron cadence such as 1m, 5m, 15m, 1h, 6h, or 1d`);
77676
+ return new BlunError(ErrorCodes.LOOP_INTERVAL_INVALID, `Invalid loop interval ${JSON.stringify(rawInterval)}`);
77661
77677
  }
77662
77678
  var MAX_LOOP_PROMPT_BYTES, LOOP_INTERVAL_PATTERN, SessionLoopMode;
77663
77679
  var init_session_loop = __esmMin((() => {
@@ -259739,6 +259755,12 @@ function blunSelectTurnTools(tools, maxContextTokens) {
259739
259755
  const lean = tools.filter((tool) => BLUN_LEAN_TOOL_NAMES.has(tool.name) || BLUN_LEAN_KEEP_RE.test(tool.name));
259740
259756
  return lean.length > 0 ? lean : tools;
259741
259757
  }
259758
+ function blunToolSuppressionReason(turnNeedsTools, eligibleTools, selectedTools) {
259759
+ if (!turnNeedsTools) return "greeting_optimization";
259760
+ if (eligibleTools.length === 0) return "no_eligible_tools";
259761
+ if (selectedTools.length < eligibleTools.length) return "context_budget_lean_set";
259762
+ return "none";
259763
+ }
259742
259764
  function isGoalOutcomeReminderOrigin(origin) {
259743
259765
  return origin?.kind === "system_trigger" && (origin.name === "goal_completion" || origin.name === "goal_blocked");
259744
259766
  }
@@ -260553,6 +260575,13 @@ var init_turn = __esmMin((() => {
260553
260575
  try {
260554
260576
  const eligibleTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools), origin);
260555
260577
  const selectedTools = turnNeedsTools ? blunSelectTurnTools(eligibleTools, this.agent.config.modelCapabilities?.max_context_tokens) : [];
260578
+ const toolSuppressionReason = blunToolSuppressionReason(turnNeedsTools, eligibleTools, selectedTools);
260579
+ this.agent.log.info("turn request tools", {
260580
+ requestPurpose: "conversation",
260581
+ toolSuppressionReason,
260582
+ eligibleToolCount: eligibleTools.length,
260583
+ selectedToolCount: selectedTools.length
260584
+ });
260556
260585
  return (await runTurn({
260557
260586
  turnId: String(turnId),
260558
260587
  signal,
@@ -401109,7 +401138,8 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
401109
401138
  aliases: [],
401110
401139
  descriptionKey: "command.loop.description",
401111
401140
  priority: 80,
401112
- argumentHint: "[interval] [prompt]",
401141
+ argumentHint: "<natürlicher Auftrag>",
401142
+ liveArgumentHint: loopInputHint,
401113
401143
  availability: (args) => {
401114
401144
  const trimmed = args.trim();
401115
401145
  if (trimmed === "") return "always";
@@ -420058,7 +420088,8 @@ function isBusy(host) {
420058
420088
  }
420059
420089
  //#endregion
420060
420090
  //#region src/tui/commands/loop.ts
420061
- const LOOP_ARGUMENT_HINT = "/loop [interval] [prompt]";
420091
+ const LOOP_ARGUMENT_HINT = "/loop <natürlicher Auftrag> · Zeitangaben dürfen überall stehen";
420092
+ const DEFAULT_LOOP_INTERVAL = "auto";
420062
420093
  const LOOP_CREATE_FILLERS = new Set([
420063
420094
  "mit",
420064
420095
  "alle",
@@ -420068,6 +420099,77 @@ const LOOP_CREATE_FILLERS = new Set([
420068
420099
  "each"
420069
420100
  ]);
420070
420101
  const LOOP_INTERVAL_TOKEN = /^\d+(?:m|h|d)$/i;
420102
+ const LOOP_NATURAL_INTERVAL = /\b(?:alle|jede(?:n|r|s)?|every|each)\s+(\d+)\s*(min(?:ute)?n?|minutes?|stunden?|hours?|tage?|days?)\b/iu;
420103
+ const LOOP_NATURAL_HALF_HOUR = /\b(?:alle|jede(?:n|r|s)?|every|each)\s+(?:halbe|half(?:\s+an)?)\s+(?:stunde|hour)\b/iu;
420104
+ const LOOP_NATURAL_SINGLE_INTERVAL = /\b(?:jede(?:n|r|s)?|every|each)\s+(minute|stunde|hour|tag|day)\b/iu;
420105
+ const LOOP_NATURAL_ADVERB_INTERVAL = /\b(stündlich|stuendlich|hourly|täglich|taeglich|daily)\b/iu;
420106
+ const LOOP_SELF_CONTROLLED = /\b(?:selbst\s+entscheiden|selbstgesteuert)\b/iu;
420107
+ function naturalLoopIntervalMatch(args) {
420108
+ const numeric = LOOP_NATURAL_INTERVAL.exec(args);
420109
+ if (numeric !== null) {
420110
+ const amount = numeric[1];
420111
+ const unit = numeric[2]?.toLowerCase() ?? "";
420112
+ const suffix = unit.startsWith("stund") || unit.startsWith("hour") ? "h" : unit.startsWith("tag") || unit.startsWith("day") ? "d" : "m";
420113
+ return {
420114
+ match: numeric,
420115
+ interval: `${amount}${suffix}`
420116
+ };
420117
+ }
420118
+ const halfHour = LOOP_NATURAL_HALF_HOUR.exec(args);
420119
+ if (halfHour !== null) return {
420120
+ match: halfHour,
420121
+ interval: "30m"
420122
+ };
420123
+ const single = LOOP_NATURAL_SINGLE_INTERVAL.exec(args);
420124
+ if (single !== null) {
420125
+ const unit = single[1]?.toLowerCase() ?? "";
420126
+ return {
420127
+ match: single,
420128
+ interval: unit === "minute" ? "1m" : unit === "tag" || unit === "day" ? "1d" : "1h"
420129
+ };
420130
+ }
420131
+ const adverb = LOOP_NATURAL_ADVERB_INTERVAL.exec(args);
420132
+ if (adverb !== null) {
420133
+ const unit = adverb[1]?.toLowerCase() ?? "";
420134
+ return {
420135
+ match: adverb,
420136
+ interval: unit === "täglich" || unit === "taeglich" || unit === "daily" ? "1d" : "1h"
420137
+ };
420138
+ }
420139
+ return null;
420140
+ }
420141
+ function parseNaturalLoopInterval(args) {
420142
+ const parsed = naturalLoopIntervalMatch(args);
420143
+ if (parsed === null) return null;
420144
+ const { match, interval } = parsed;
420145
+ const prompt = `${args.slice(0, match.index)} ${args.slice(match.index + match[0].length)}`.replace(/\s+/gu, " ").trim();
420146
+ if (prompt.length === 0) return { kind: "error" };
420147
+ return {
420148
+ kind: "create",
420149
+ interval,
420150
+ prompt
420151
+ };
420152
+ }
420153
+ function naturalLoopIntervalText(interval) {
420154
+ if (interval === "auto") return "Selbstgesteuert";
420155
+ const match = /^([1-9]\d*)(m|h|d)$/i.exec(interval);
420156
+ if (match === null) return "";
420157
+ const amount = Number(match[1]);
420158
+ const unit = match[2]?.toLowerCase();
420159
+ if (unit === "m") return `Erkannt: alle ${String(amount)} ${amount === 1 ? "Minute" : "Minuten"}`;
420160
+ if (unit === "h") return `Erkannt: alle ${String(amount)} ${amount === 1 ? "Stunde" : "Stunden"}`;
420161
+ return `Erkannt: alle ${String(amount)} ${amount === 1 ? "Tag" : "Tage"}`;
420162
+ }
420163
+ function loopInputHint(rawArgs) {
420164
+ const args = rawArgs.trim();
420165
+ if (args.length === 0) return "Natürlichen Auftrag eingeben; Zeitangaben dürfen überall stehen";
420166
+ if (/^(?:status|pause|paused|resume|stop)$/i.test(args)) return "";
420167
+ const natural = naturalLoopIntervalMatch(args);
420168
+ if (natural !== null) return naturalLoopIntervalText(natural.interval);
420169
+ const explicit = /^(?:start\s+)?([1-9]\d*(?:m|h|d))\b/i.exec(args);
420170
+ if (explicit?.[1] !== void 0) return naturalLoopIntervalText(explicit[1].toLowerCase());
420171
+ return "Selbstgesteuert";
420172
+ }
420071
420173
  function parseLoopCommand(rawArgs) {
420072
420174
  const args = rawArgs.trim();
420073
420175
  if (args.length === 0 || args.toLowerCase() === "status") return { kind: "status" };
@@ -420079,13 +420181,35 @@ function parseLoopCommand(rawArgs) {
420079
420181
  if (action === "stop") return { kind: "stop" };
420080
420182
  }
420081
420183
  let startIndex = action === "start" ? 1 : 0;
420184
+ const createArgs = tokens.slice(startIndex).join(" ");
420185
+ const natural = parseNaturalLoopInterval(createArgs);
420186
+ if (natural !== null) return natural;
420187
+ const selfControlled = LOOP_SELF_CONTROLLED.exec(createArgs);
420188
+ if (selfControlled !== null) {
420189
+ const prompt = `${createArgs.slice(0, selfControlled.index)} ${createArgs.slice(selfControlled.index + selfControlled[0].length)}`.replace(/\s+/gu, " ").trim();
420190
+ if (prompt.length === 0) return { kind: "error" };
420191
+ return {
420192
+ kind: "create",
420193
+ interval: "auto",
420194
+ prompt
420195
+ };
420196
+ }
420082
420197
  if (LOOP_CREATE_FILLERS.has(tokens[startIndex]?.toLowerCase() ?? "")) startIndex += 1;
420083
420198
  const interval = tokens[startIndex];
420084
- const prompt = tokens.slice(startIndex + 1).join(" ").trim();
420085
- if (interval === void 0 || !LOOP_INTERVAL_TOKEN.test(interval) || prompt.length === 0) return { kind: "error" };
420199
+ if (interval !== void 0 && LOOP_INTERVAL_TOKEN.test(interval)) {
420200
+ const prompt = tokens.slice(startIndex + 1).join(" ").trim();
420201
+ if (prompt.length === 0) return { kind: "error" };
420202
+ return {
420203
+ kind: "create",
420204
+ interval,
420205
+ prompt
420206
+ };
420207
+ }
420208
+ const prompt = tokens.slice(startIndex).join(" ").trim();
420209
+ if (prompt.length === 0) return { kind: "error" };
420086
420210
  return {
420087
420211
  kind: "create",
420088
- interval,
420212
+ interval: DEFAULT_LOOP_INTERVAL,
420089
420213
  prompt
420090
420214
  };
420091
420215
  }
@@ -501930,6 +502054,9 @@ var PersonalMemoryController = class {
501930
502054
  };
501931
502055
  //#endregion
501932
502056
  //#region src/tui/constant/scrollback.ts
502057
+ function shouldEnableScrollbackMouseTracking(buffer) {
502058
+ return buffer !== void 0 && buffer.isActive();
502059
+ }
501933
502060
  const ENABLE_SCROLLBACK_MOUSE_TRACKING = "\x1B[?1000h\x1B[?1006h";
501934
502061
  const DISABLE_SCROLLBACK_MOUSE_TRACKING = "\x1B[?1000l\x1B[?1006l";
501935
502062
  //#endregion
@@ -502286,7 +502413,7 @@ var BottomPinnedTUI = class extends TUI {
502286
502413
  }
502287
502414
  const buffer = this.scrollbackBuffer;
502288
502415
  buffer?.updateSnapshot(clipped, scrollViewportRows);
502289
- this.setMouseTracking(buffer !== void 0 && buffer.totalLines > 0);
502416
+ this.setMouseTracking(shouldEnableScrollbackMouseTracking(buffer));
502290
502417
  if (buffer !== void 0 && buffer.isActive() && terminalRows > 0) {
502291
502418
  const pinnedLines = [];
502292
502419
  for (let i = chromeAt; i < blocks.length; i++) {
@@ -510056,8 +510183,10 @@ var CustomEditor = class extends Editor {
510056
510183
  consumingPaste = false;
510057
510184
  consumeBuffer = "";
510058
510185
  argumentHints = /* @__PURE__ */ new Map();
510059
- setArgumentHints(hints) {
510186
+ argumentHintResolvers = /* @__PURE__ */ new Map();
510187
+ setArgumentHints(hints, resolvers = /* @__PURE__ */ new Map()) {
510060
510188
  this.argumentHints = hints;
510189
+ this.argumentHintResolvers = resolvers;
510061
510190
  }
510062
510191
  constructor(tui, options = {}) {
510063
510192
  const theme = createEditorTheme();
@@ -510151,12 +510280,18 @@ var CustomEditor = class extends Editor {
510151
510280
  computeArgumentHint() {
510152
510281
  if (this.inputMode === "bash") return void 0;
510153
510282
  const text = this.getText();
510154
- const match = /^\/(\S+)( ?)$/.exec(text);
510283
+ const match = /^\/(\S+)(?:\s+([\s\S]*))?$/.exec(text);
510155
510284
  if (match === null) return void 0;
510156
510285
  const cmd = match[1];
510157
- const trailingSpace = match[2] ?? "";
510286
+ const args = match[2] ?? "";
510287
+ const trailingSpace = text.endsWith(" ") ? " " : "";
510158
510288
  if (cmd === void 0) return void 0;
510159
510289
  if (this.hasAutocompleteActivity() && trailingSpace.length === 0) return void 0;
510290
+ const resolver = this.argumentHintResolvers.get(cmd);
510291
+ if (resolver !== void 0) {
510292
+ const resolved = resolver(args);
510293
+ if (resolved.length > 0) return args.length > 0 ? ` · ${resolved}` : ` ${resolved}`;
510294
+ }
510160
510295
  const hint = this.argumentHints.get(cmd);
510161
510296
  if (hint === void 0) return void 0;
510162
510297
  const { line, col } = this.getCursor();
@@ -512061,20 +512196,26 @@ var BlunTUI = class {
512061
512196
  aliases: cmd.aliases,
512062
512197
  description: cmd.description,
512063
512198
  ...cmd.argumentHint !== void 0 ? { argumentHint: cmd.argumentHint } : {},
512199
+ ...cmd.liveArgumentHint !== void 0 ? { liveArgumentHint: cmd.liveArgumentHint } : {},
512064
512200
  ...completer !== void 0 ? { getArgumentCompletions: (prefix) => completer(prefix) } : {}
512065
512201
  };
512066
512202
  });
512067
512203
  const provider = new FileMentionProvider(slashCommands, this.state.appState.workDir, this.fdPath, this.state.appState.additionalDirs, () => this.state.appState.inputMode, this.mentionFileSearch);
512068
512204
  this.state.editor.setAutocompleteProvider(provider);
512069
512205
  const argumentHints = /* @__PURE__ */ new Map();
512206
+ const argumentHintResolvers = /* @__PURE__ */ new Map();
512070
512207
  for (const cmd of slashCommands) {
512071
512208
  if (cmd.argumentHint === void 0) continue;
512072
512209
  const visibleHint = cmd.description?.trim();
512073
512210
  if (visibleHint === void 0 || visibleHint.length === 0) continue;
512074
512211
  argumentHints.set(cmd.name, visibleHint);
512075
512212
  for (const alias of cmd.aliases ?? []) argumentHints.set(alias, visibleHint);
512213
+ if (cmd.liveArgumentHint !== void 0) {
512214
+ argumentHintResolvers.set(cmd.name, cmd.liveArgumentHint);
512215
+ for (const alias of cmd.aliases ?? []) argumentHintResolvers.set(alias, cmd.liveArgumentHint);
512216
+ }
512076
512217
  }
512077
- this.state.editor.setArgumentHints(argumentHints);
512218
+ this.state.editor.setArgumentHints(argumentHints, argumentHintResolvers);
512078
512219
  }
512079
512220
  refreshSlashCommandAutocomplete() {
512080
512221
  this.setupAutocomplete();
@@ -514681,16 +514822,44 @@ function readTelegramUpdateRecipients(stateDir = defaultTelegramStateDir()) {
514681
514822
  return [];
514682
514823
  }
514683
514824
  }
514825
+ function claimTelegramUpdateNotice(version, chatId, receiptDir = join(homedir(), ".blun", "updates", "telegram-notices")) {
514826
+ const safeVersion = version.trim().replace(/[^0-9A-Za-z._-]/gu, "_").slice(0, 64);
514827
+ if (safeVersion.length === 0 || !TELEGRAM_DM_ID.test(chatId)) return null;
514828
+ const receiptPath = join(receiptDir, `${safeVersion}-${chatId}.sent`);
514829
+ try {
514830
+ mkdirSync(receiptDir, {
514831
+ recursive: true,
514832
+ mode: 448
514833
+ });
514834
+ writeFileSync(receiptPath, `${(/* @__PURE__ */ new Date()).toISOString()}\n`, {
514835
+ encoding: "utf8",
514836
+ flag: "wx",
514837
+ mode: 384
514838
+ });
514839
+ return receiptPath;
514840
+ } catch {
514841
+ return null;
514842
+ }
514843
+ }
514684
514844
  async function sendTelegramUpdateNotice(text, options = {}) {
514685
514845
  const stateDir = options.stateDir ?? defaultTelegramStateDir();
514686
514846
  const configured = hasConfiguredToken(stateDir);
514687
514847
  const recipients = configured ? readTelegramUpdateRecipients(stateDir) : [];
514688
514848
  const send = options.send ?? ((chatId, message) => sendReplyFallback(chatId, message));
514689
514849
  let sent = 0;
514690
- for (const chatId of recipients) if (await send(chatId, text).catch(() => false)) sent += 1;
514850
+ let attempted = 0;
514851
+ for (const chatId of recipients) {
514852
+ const receiptPath = options.version === void 0 ? void 0 : claimTelegramUpdateNotice(options.version, chatId, options.receiptDir);
514853
+ if (options.version !== void 0 && receiptPath === null) continue;
514854
+ attempted += 1;
514855
+ if (await send(chatId, text).catch(() => false)) sent += 1;
514856
+ else if (receiptPath !== void 0) try {
514857
+ unlinkSync(receiptPath);
514858
+ } catch {}
514859
+ }
514691
514860
  return {
514692
514861
  configured,
514693
- attempted: recipients.length,
514862
+ attempted,
514694
514863
  sent
514695
514864
  };
514696
514865
  }
@@ -514843,7 +515012,7 @@ async function runShell(opts, version, updateStartupNotice) {
514843
515012
  workDir,
514844
515013
  startupNotice: configWarning,
514845
515014
  onStartupNoticeShown: updateStartupNotice === void 0 || updateNoticeText === void 0 ? void 0 : async () => {
514846
- const delivery = await sendTelegramUpdateNotice(updateNoticeText);
515015
+ const delivery = await sendTelegramUpdateNotice(updateNoticeText, { version: updateStartupNotice.details.version });
514847
515016
  if (!delivery.configured || delivery.attempted === 0 || delivery.sent === delivery.attempted) await updateStartupNotice.acknowledge();
514848
515017
  }
514849
515018
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.45",
3
+ "version": "9.1.47",
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": {