blun-king-cli 9.1.30 → 9.1.32

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/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.30
12
+ npm install -g blun-king-cli@9.1.32
13
13
  ```
14
14
 
15
15
  ## Reproduzierbares Staging und Packen
@@ -22,6 +22,7 @@ const {
22
22
  seedStandardTools,
23
23
  } = require('./standard-tools-bootstrap');
24
24
  const { CORE_LOADED_MESSAGE } = require('./core-bootstrap');
25
+ const { prepareManagedNodeRuntime } = require('./node-runtime');
25
26
  const { acquireSharedRuntimeLease, tryAcquireUpdateLease } = require('./update-lease');
26
27
  const { runExplicitUpdate, runUpdateNotice } = require('./update-notice');
27
28
  const {
@@ -182,6 +183,33 @@ function installTelegramForProfile(packageRoot, blunDir) {
182
183
  }
183
184
  }
184
185
 
186
+ function spawnManagedLauncher(binary, cwd) {
187
+ return new Promise((resolve, reject) => {
188
+ const child = spawn(binary, process.argv.slice(1), {
189
+ cwd,
190
+ env: process.env,
191
+ stdio: 'inherit',
192
+ windowsHide: true,
193
+ });
194
+ child.once('error', reject);
195
+ child.once('exit', (code, signal) => {
196
+ if (Number.isInteger(code)) {
197
+ resolve(code);
198
+ return;
199
+ }
200
+ if (signal === 'SIGINT') {
201
+ resolve(130);
202
+ return;
203
+ }
204
+ if (signal === 'SIGTERM') {
205
+ resolve(143);
206
+ return;
207
+ }
208
+ resolve(1);
209
+ });
210
+ });
211
+ }
212
+
185
213
  async function runLauncher(options = {}) {
186
214
  const callerCwd = process.cwd();
187
215
  const mode = options.mode || launcherModeFromArgv(process.argv);
@@ -278,6 +306,26 @@ async function runLauncher(options = {}) {
278
306
  return;
279
307
  }
280
308
 
309
+ let privatePaths;
310
+ const getPrivatePaths = () => {
311
+ privatePaths ||= resolveLauncherPrivatePaths();
312
+ return privatePaths;
313
+ };
314
+ const nodeRuntime = await prepareManagedNodeRuntime({
315
+ getBlunDir: () => getPrivatePaths().blunHome,
316
+ });
317
+ if (nodeRuntime.kind === 'failed') {
318
+ process.stderr.write(`${nodeRuntime.message}\n`);
319
+ process.exitCode = 1;
320
+ return;
321
+ }
322
+ if (nodeRuntime.kind === 'managed') {
323
+ process.stdout.write('BLUN hat die passende Node.js-Laufzeit eingerichtet.\n');
324
+ await releaseNotice();
325
+ process.exitCode = await spawnManagedLauncher(nodeRuntime.binary, callerCwd);
326
+ return;
327
+ }
328
+
281
329
  if (ARGS.some((arg) => arg === '--help' || arg === '-h')) {
282
330
  process.stdout.write(launcherHelpText());
283
331
  const env = createLauncherEnvironment(process.env, mode, readPackageVersion());
@@ -288,8 +336,7 @@ async function runLauncher(options = {}) {
288
336
  return;
289
337
  }
290
338
 
291
- const privatePaths = resolveLauncherPrivatePaths();
292
- const blunDir = privatePaths.blunHome;
339
+ const blunDir = getPrivatePaths().blunHome;
293
340
  ensurePrivateDirectory(blunDir);
294
341
 
295
342
  // --- 1. Oeffentlicher npm-Update-Dialog. -------------------------------
@@ -356,4 +403,9 @@ async function runLauncher(options = {}) {
356
403
  }
357
404
  }
358
405
 
359
- module.exports = { resolveLauncherPrivatePaths, runLauncher, shouldDetachProtectedCore };
406
+ module.exports = {
407
+ resolveLauncherPrivatePaths,
408
+ runLauncher,
409
+ shouldDetachProtectedCore,
410
+ spawnManagedLauncher,
411
+ };
@@ -0,0 +1,186 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('node:crypto');
4
+ const fs = require('node:fs');
5
+ const https = require('node:https');
6
+ const os = require('node:os');
7
+ const path = require('node:path');
8
+ const { spawnSync } = require('node:child_process');
9
+
10
+ const NODE_VERSION = '24.15.0';
11
+ const MAX_ARCHIVE_BYTES = 100 * 1024 * 1024;
12
+ const DISTRIBUTIONS = {
13
+ 'darwin-arm64': {
14
+ archive: `node-v${NODE_VERSION}-darwin-arm64.tar.gz`,
15
+ binary: path.join('bin', 'node'),
16
+ format: 'tar.gz',
17
+ sha256: '372331b969779ab5d15b949884fc6eaf88d5afe87bde8ba881d6400b9100ffc4',
18
+ },
19
+ 'darwin-x64': {
20
+ archive: `node-v${NODE_VERSION}-darwin-x64.tar.gz`,
21
+ binary: path.join('bin', 'node'),
22
+ format: 'tar.gz',
23
+ sha256: 'ffd5ee293467927f3ee731a553eb88fd1f48cf74eebc2d74a6babe4af228673b',
24
+ },
25
+ 'win32-arm64': {
26
+ archive: `node-v${NODE_VERSION}-win-arm64.zip`,
27
+ binary: 'node.exe',
28
+ format: 'zip',
29
+ sha256: 'c9eb7402eda26e2ba7e44b6727fc85a8de56c5095b1f71ebd3062892211aa116',
30
+ },
31
+ 'win32-x64': {
32
+ archive: `node-v${NODE_VERSION}-win-x64.zip`,
33
+ binary: 'node.exe',
34
+ format: 'zip',
35
+ sha256: 'cc5149eabd53779ce1e7bdc5401643622d0c7e6800ade18928a767e940bb0e62',
36
+ },
37
+ };
38
+
39
+ function distributionFor(platform, arch) {
40
+ return DISTRIBUTIONS[`${platform}-${arch}`] || null;
41
+ }
42
+
43
+ function sha256File(file) {
44
+ const hash = crypto.createHash('sha256');
45
+ hash.update(fs.readFileSync(file));
46
+ return hash.digest('hex');
47
+ }
48
+
49
+ function downloadFile(url, destination, redirectsLeft = 3) {
50
+ return new Promise((resolve, reject) => {
51
+ const request = https.get(url, { timeout: 30_000 }, (response) => {
52
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
53
+ response.resume();
54
+ if (redirectsLeft <= 0) {
55
+ reject(new Error('Zu viele Weiterleitungen beim Node.js-Download.'));
56
+ return;
57
+ }
58
+ const redirect = new URL(response.headers.location, url);
59
+ if (redirect.protocol !== 'https:') {
60
+ reject(new Error('Unsichere Weiterleitung beim Node.js-Download abgelehnt.'));
61
+ return;
62
+ }
63
+ downloadFile(redirect.href, destination, redirectsLeft - 1).then(resolve, reject);
64
+ return;
65
+ }
66
+
67
+ if (response.statusCode !== 200) {
68
+ response.resume();
69
+ reject(new Error(`Node.js-Download antwortete mit HTTP ${response.statusCode}.`));
70
+ return;
71
+ }
72
+
73
+ const contentLength = Number(response.headers['content-length'] || 0);
74
+ if (contentLength > MAX_ARCHIVE_BYTES) {
75
+ response.destroy();
76
+ reject(new Error('Node.js-Download ist groesser als erwartet.'));
77
+ return;
78
+ }
79
+
80
+ let received = 0;
81
+ const output = fs.createWriteStream(destination, { flags: 'wx' });
82
+ response.on('data', (chunk) => {
83
+ received += chunk.length;
84
+ if (received > MAX_ARCHIVE_BYTES) {
85
+ response.destroy(new Error('Node.js-Download ist groesser als erwartet.'));
86
+ }
87
+ });
88
+ response.on('error', reject);
89
+ output.on('error', reject);
90
+ output.on('finish', () => output.close(resolve));
91
+ response.pipe(output);
92
+ });
93
+ request.on('error', reject);
94
+ request.on('timeout', () => request.destroy(new Error('Zeitlimit beim Node.js-Download erreicht.')));
95
+ });
96
+ }
97
+
98
+ function usableNode(binary) {
99
+ if (!fs.existsSync(binary)) return false;
100
+ const result = spawnSync(binary, ['--version'], { encoding: 'utf8', timeout: 5_000 });
101
+ return result.status === 0 && result.stdout.trim() === `v${NODE_VERSION}`;
102
+ }
103
+
104
+ function archiveRootName(distribution) {
105
+ const suffix = distribution.format === 'zip' ? '.zip' : '.tar.gz';
106
+ if (!distribution.archive.endsWith(suffix)) {
107
+ throw new Error('Unbekanntes Format der Node.js-Laufzeit.');
108
+ }
109
+ return distribution.archive.slice(0, -suffix.length);
110
+ }
111
+
112
+ function unpackArchive(archive, destination, distribution, platform) {
113
+ const command = platform === 'win32'
114
+ ? path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'tar.exe')
115
+ : '/usr/bin/tar';
116
+ const args = distribution.format === 'zip'
117
+ ? ['-xf', archive, '-C', destination]
118
+ : ['-xzf', archive, '-C', destination];
119
+ return spawnSync(command, args, {
120
+ encoding: 'utf8',
121
+ timeout: 120_000,
122
+ });
123
+ }
124
+
125
+ async function ensureManagedNode(blunHome, platform, arch) {
126
+ const distribution = distributionFor(platform, arch);
127
+ if (!distribution) {
128
+ throw new Error(
129
+ `Automatische Node.js-Einrichtung wird fuer ${platform}-${arch} noch nicht unterstuetzt.`,
130
+ );
131
+ }
132
+
133
+ const installDir = path.join(
134
+ blunHome,
135
+ 'runtime',
136
+ 'node',
137
+ `v${NODE_VERSION}-${platform}-${arch}`,
138
+ );
139
+ const binary = path.join(installDir, distribution.binary);
140
+ if (usableNode(binary)) return binary;
141
+
142
+ const staging = fs.mkdtempSync(path.join(os.tmpdir(), 'blun-node-runtime-'));
143
+ try {
144
+ const archive = path.join(staging, distribution.archive);
145
+ await downloadFile(
146
+ `https://nodejs.org/dist/v${NODE_VERSION}/${distribution.archive}`,
147
+ archive,
148
+ );
149
+
150
+ const actualSha = sha256File(archive);
151
+ if (actualSha !== distribution.sha256) {
152
+ throw new Error('Die SHA-256-Pruefsumme der Node.js-Laufzeit stimmt nicht.');
153
+ }
154
+
155
+ const extractedName = archiveRootName(distribution);
156
+ const extractedDir = path.join(staging, extractedName);
157
+ const unpacked = unpackArchive(archive, staging, distribution, platform);
158
+ if (unpacked.status !== 0 || !usableNode(path.join(extractedDir, distribution.binary))) {
159
+ const detail = (unpacked.stderr || '').trim();
160
+ throw new Error(
161
+ `Die Node.js-Laufzeit konnte nicht entpackt werden${detail ? `: ${detail}` : '.'}`,
162
+ );
163
+ }
164
+
165
+ fs.mkdirSync(path.dirname(installDir), { recursive: true });
166
+ if (usableNode(binary)) return binary;
167
+ fs.rmSync(installDir, { recursive: true, force: true });
168
+ fs.renameSync(extractedDir, installDir);
169
+ if (!usableNode(binary)) throw new Error('Die installierte Node.js-Laufzeit startet nicht.');
170
+ return binary;
171
+ } finally {
172
+ fs.rmSync(staging, { recursive: true, force: true });
173
+ }
174
+ }
175
+
176
+ module.exports = {
177
+ DISTRIBUTIONS,
178
+ MAX_ARCHIVE_BYTES,
179
+ NODE_VERSION,
180
+ distributionFor,
181
+ ensureManagedNode,
182
+ archiveRootName,
183
+ sha256File,
184
+ unpackArchive,
185
+ usableNode,
186
+ };
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ const { ensureManagedNode } = require('./managed-node');
4
+ const { unsupportedNodeMessage } = require('./node-version');
5
+
6
+ async function prepareManagedNodeRuntime(options = {}) {
7
+ const version = options.version || process.versions.node;
8
+ const platform = options.platform || process.platform;
9
+ const arch = options.arch || process.arch;
10
+ const message = unsupportedNodeMessage(version, platform);
11
+ if (message === null) return { kind: 'current' };
12
+ if (platform !== 'darwin' && platform !== 'win32') return { kind: 'failed', message };
13
+
14
+ try {
15
+ const blunDir = options.blunDir || options.getBlunDir?.();
16
+ const binary = await (options.ensureManagedNode || ensureManagedNode)(
17
+ blunDir,
18
+ platform,
19
+ arch,
20
+ );
21
+ return { binary, kind: 'managed' };
22
+ } catch (error) {
23
+ return {
24
+ kind: 'failed',
25
+ message: [
26
+ 'Die automatische Node.js-Einrichtung ist fehlgeschlagen.',
27
+ error && error.message ? error.message : String(error),
28
+ message,
29
+ ].join('\n'),
30
+ };
31
+ }
32
+ }
33
+
34
+ module.exports = { prepareManagedNodeRuntime };
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ const MINIMUM_NODE_VERSION = '24.15.0';
4
+
5
+ function parseNodeVersion(version) {
6
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(String(version));
7
+ return match ? match.slice(1).map(Number) : null;
8
+ }
9
+
10
+ function supportsNodeVersion(version) {
11
+ const actual = parseNodeVersion(version);
12
+ const minimum = parseNodeVersion(MINIMUM_NODE_VERSION);
13
+ if (!actual || !minimum) return false;
14
+
15
+ for (let index = 0; index < minimum.length; index += 1) {
16
+ if (actual[index] > minimum[index]) return true;
17
+ if (actual[index] < minimum[index]) return false;
18
+ }
19
+ return true;
20
+ }
21
+
22
+ function unsupportedNodeMessage(version, platform) {
23
+ if (supportsNodeVersion(version)) return null;
24
+
25
+ const lines = [
26
+ '',
27
+ 'BLUN kann mit dieser Node.js-Version nicht starten.',
28
+ `Installiert: Node.js ${version}`,
29
+ `Benoetigt: Node.js ${MINIMUM_NODE_VERSION} oder neuer`,
30
+ '',
31
+ ];
32
+
33
+ if (platform === 'darwin') {
34
+ lines.push(`Falls die automatische Einrichtung scheitert: nvm install ${MINIMUM_NODE_VERSION}`);
35
+ } else if (platform === 'win32') {
36
+ lines.push(`Falls die automatische Einrichtung scheitert: Node.js ${MINIMUM_NODE_VERSION} oder neuer von https://nodejs.org/ installieren.`);
37
+ } else {
38
+ lines.push(`Node.js ${MINIMUM_NODE_VERSION} oder neuer installieren: https://nodejs.org/`);
39
+ }
40
+ lines.push('Danach BLUN aktualisieren: npm i -g blun-king-cli@latest', '');
41
+ return lines.join('\n');
42
+ }
43
+
44
+ module.exports = {
45
+ MINIMUM_NODE_VERSION,
46
+ parseNodeVersion,
47
+ supportsNodeVersion,
48
+ unsupportedNodeMessage,
49
+ };
package/blun.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // BLUN_BUILD_INPUT_SHA256:3d728fcf187e7f3b481337a4b5e3427abf12a7218a8c40a2061f77ee20e2dc17
2
+ // BLUN_BUILD_INPUT_SHA256:a7df37740da4f38cdb11b51de60021135cbc55aec8643f9501c9c946c3b67c0b
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);
@@ -497750,6 +497750,8 @@ var AuthFlowController = class {
497750
497750
  host;
497751
497751
  managedAccountRefreshSequence = 0;
497752
497752
  managedQuotaRefreshSequence = 0;
497753
+ managedQuotaRetryTimer;
497754
+ managedQuotaRetryAttempt = 0;
497753
497755
  constructor(host) {
497754
497756
  this.host = host;
497755
497757
  }
@@ -497803,24 +497805,69 @@ var AuthFlowController = class {
497803
497805
  maxContextTokens
497804
497806
  };
497805
497807
  }
497806
- async refreshManagedQuotaWindows() {
497808
+ async refreshManagedQuotaWindows(options = {}) {
497807
497809
  const { host } = this;
497808
497810
  const sessionId = host.state.appState.sessionId;
497809
497811
  if (sessionId.length === 0) return;
497812
+ if (options.retry !== true) {
497813
+ this.clearManagedQuotaRetry();
497814
+ this.managedQuotaRetryAttempt = 0;
497815
+ }
497810
497816
  const sequence = ++this.managedQuotaRefreshSequence;
497811
497817
  let usage;
497812
497818
  try {
497813
497819
  usage = await host.harness.auth.getManagedQuota(this.managedProviderName());
497814
497820
  } catch {
497821
+ this.handleManagedQuotaFailure("unavailable", sessionId);
497815
497822
  return;
497816
497823
  }
497817
497824
  if (sequence !== this.managedQuotaRefreshSequence || host.state.appState.sessionId !== sessionId) return;
497818
497825
  if (usage?.kind !== "ok") {
497819
- if (usage?.code === "unauthenticated" || usage?.code === "invalid_payload") host.setAppState({ managedQuotaWindows: void 0 });
497826
+ const error = usage?.code === "unauthenticated" ? "unauthenticated" : usage?.code === "invalid_payload" ? "invalid_payload" : "unavailable";
497827
+ if (error === "unauthenticated") {
497828
+ this.clearManagedQuotaRetry();
497829
+ this.managedQuotaRetryAttempt = 0;
497830
+ host.setAppState({
497831
+ managedQuotaWindows: void 0,
497832
+ managedQuotaError: error
497833
+ });
497834
+ } else this.handleManagedQuotaFailure(error, sessionId);
497820
497835
  return;
497821
497836
  }
497822
497837
  const managedQuotaWindows = normalizeManagedQuotaWindows(usage.limits);
497823
- host.setAppState({ managedQuotaWindows });
497838
+ if (managedQuotaWindows === void 0) {
497839
+ this.handleManagedQuotaFailure("invalid_payload", sessionId);
497840
+ return;
497841
+ }
497842
+ this.clearManagedQuotaRetry();
497843
+ this.managedQuotaRetryAttempt = 0;
497844
+ host.setAppState({
497845
+ managedQuotaWindows,
497846
+ managedQuotaError: void 0
497847
+ });
497848
+ }
497849
+ handleManagedQuotaFailure(error, sessionId) {
497850
+ const { host } = this;
497851
+ if (error === "invalid_payload") host.setAppState({
497852
+ managedQuotaWindows: void 0,
497853
+ managedQuotaError: error
497854
+ });
497855
+ else if (host.state.appState.managedQuotaWindows === void 0) host.setAppState({ managedQuotaError: error });
497856
+ if (this.managedQuotaRetryAttempt >= 2 || this.managedQuotaRetryTimer !== void 0) return;
497857
+ const delayMs = this.managedQuotaRetryAttempt === 0 ? 750 : 3e3;
497858
+ this.managedQuotaRetryAttempt += 1;
497859
+ this.managedQuotaRetryTimer = setTimeout(() => {
497860
+ this.managedQuotaRetryTimer = void 0;
497861
+ if (host.state.appState.sessionId !== sessionId) return;
497862
+ this.refreshManagedQuotaWindows({ retry: true });
497863
+ }, delayMs);
497864
+ this.managedQuotaRetryTimer.unref?.();
497865
+ }
497866
+ clearManagedQuotaRetry() {
497867
+ if (this.managedQuotaRetryTimer !== void 0) {
497868
+ clearTimeout(this.managedQuotaRetryTimer);
497869
+ this.managedQuotaRetryTimer = void 0;
497870
+ }
497824
497871
  }
497825
497872
  managedProviderName() {
497826
497873
  return DEFAULT_OAUTH_PROVIDER_NAME;
@@ -497859,7 +497906,8 @@ var AuthFlowController = class {
497859
497906
  contextUsage: 0,
497860
497907
  sessionTitle: null,
497861
497908
  managedAccountContextTokens: void 0,
497862
- managedQuotaWindows: void 0
497909
+ managedQuotaWindows: void 0,
497910
+ managedQuotaError: void 0
497863
497911
  });
497864
497912
  this.host.appendStartupNotice(notice);
497865
497913
  this.host.setStartupReady();
@@ -497913,7 +497961,8 @@ var AuthFlowController = class {
497913
497961
  sessionTitle: null,
497914
497962
  ...options?.clearCustomerAccount === false ? {} : {
497915
497963
  managedAccountContextTokens: void 0,
497916
- managedQuotaWindows: void 0
497964
+ managedQuotaWindows: void 0,
497965
+ managedQuotaError: void 0
497917
497966
  }
497918
497967
  });
497919
497968
  await this.host.refreshSkillCommands();
@@ -497959,7 +498008,8 @@ var AuthFlowController = class {
497959
498008
  contextTokens: 0,
497960
498009
  ...options?.clearCustomerAccount === false ? {} : {
497961
498010
  managedAccountContextTokens: void 0,
497962
- managedQuotaWindows: void 0
498011
+ managedQuotaWindows: void 0,
498012
+ managedQuotaError: void 0
497963
498013
  }
497964
498014
  });
497965
498015
  }
@@ -497990,6 +498040,8 @@ var AuthFlowController = class {
497990
498040
  return result;
497991
498041
  }
497992
498042
  invalidateManagedAccountRefreshes() {
498043
+ this.clearManagedQuotaRetry();
498044
+ this.managedQuotaRetryAttempt = 0;
497993
498045
  this.managedAccountRefreshSequence += 1;
497994
498046
  this.managedQuotaRefreshSequence += 1;
497995
498047
  }
@@ -505454,7 +505506,7 @@ var FooterComponent = class {
505454
505506
  const pad = Math.max(0, width - visibleWidth(shownLeft) - rightWidth);
505455
505507
  line1 = shownLeft + " ".repeat(pad) + right;
505456
505508
  }
505457
- const quotaLines = state.managedQuotaWindows === void 0 ? [] : formatManagedQuotaFooterLines(state.managedQuotaWindows, colors, width);
505509
+ const quotaLines = state.managedQuotaWindows === void 0 ? state.managedQuotaError === void 0 ? [] : [truncateToWidth(chalk.hex(colors.warning)(uiText(state.managedQuotaError === "unauthenticated" ? "usage.plan.error.unauthenticated" : state.managedQuotaError === "invalid_payload" ? "usage.plan.error.invalidPayload" : "usage.plan.error.unavailable")), width)] : formatManagedQuotaFooterLines(state.managedQuotaWindows, colors, width);
505458
505510
  return [truncateToWidth(line1, width), ...quotaLines];
505459
505511
  }
505460
505512
  syncGoalClock(goal) {
@@ -511169,7 +511221,7 @@ var BlunTUI = class {
511169
511221
  if (this.session !== void 0) {
511170
511222
  await this.refreshPersonalMemory(true);
511171
511223
  await this.refreshCustomerMistakeConsent();
511172
- await this.authFlow.refreshManagedQuotaWindows();
511224
+ this.authFlow.refreshManagedQuotaWindows();
511173
511225
  }
511174
511226
  this.showTmuxKeyboardWarningIfNeeded();
511175
511227
  this.startTelegramChannel();
@@ -513442,7 +513494,7 @@ var BlunTUI = class {
513442
513494
  if (applyStartupModes) {
513443
513495
  await this.refreshPersonalMemory(true);
513444
513496
  await this.refreshCustomerMistakeConsent();
513445
- await this.authFlow.refreshManagedQuotaWindows();
513497
+ this.authFlow.refreshManagedQuotaWindows();
513446
513498
  await this.promptStartupResumeGoalIfNeeded();
513447
513499
  }
513448
513500
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.30",
3
+ "version": "9.1.32",
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": {