blun-king-cli 9.1.490 → 9.1.492

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.1.492 - 2026-08-30
4
+
5
+ - Keeps an authorized Telegram group message pending when an in-flight delivery temporarily blocks Ctrl+S or Escape, then retries it without requiring another key press.
6
+ - Prevents unreleased group arrivals from arming the delivery controller before the user authorizes them.
7
+ - Makes a current changelog entry mandatory before npm can pack or publish the package.
8
+ - Adds an external release check that compares npm latest, npm package integrity, the public update manifest, and the public changelog before a release may be reported complete.
9
+
10
+ ## 9.1.491 - 2026-08-30
11
+
12
+ - Restores real-time private Telegram priority: a user DM now auto-authorizes delivery into active work instead of waiting behind the manual queue-release gate.
13
+ - Keeps Ctrl+S batch release and one-message-per-Escape control for the remaining console and channel queue.
14
+
3
15
  ## 9.1.490 - 2026-08-30
4
16
 
5
17
  - Corrects the packaged release history by recording the unpublished 9.1.487 build and replacing the incomplete 9.1.488 summary with the changes verified from the release commits.
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.490
12
+ npm install -g blun-king-cli@9.1.492
13
13
 
14
14
  Start
15
15
  -----
@@ -63,7 +63,13 @@ ab, ohne den geschriebenen Entwurf zu löschen. Das gilt auch bei
63
63
  Autovervollständigung, Geistervorschlägen, Bash-Eingabe und einer offenen
64
64
  Mehrzeileneingabe.
65
65
 
66
- Version 9.1.490 stellt außerdem die interne Todo-Liste wieder her. Deutsche
66
+ Version 9.1.492 schützt Veröffentlichungen zusätzlich mit einer verpflichtenden
67
+ Metadatenprüfung. Packen und Veröffentlichen brechen ab, wenn Paketversion,
68
+ erster Changelog-Eintrag oder Installationshinweise auseinanderlaufen. Die
69
+ abschließende externe Prüfung vergleicht npm, Paketintegrität, öffentliches
70
+ Update-Manifest und öffentliche Changelog-Seite.
71
+
72
+ Version 9.1.491 stellt außerdem die interne Todo-Liste wieder her. Deutsche
67
73
  Aufgabenlisten-Befehle wählen wieder TodoList statt der getrennten TaskList für
68
74
  Hintergrundprozesse. Lesen, Ersetzen, Aktualisieren und Leeren funktionieren in
69
75
  derselben Sitzung; eine vollständig erledigte Liste wird aus der Anzeige
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.490
12
+ npm install -g blun-king-cli@9.1.492
13
13
  ```
14
14
 
15
15
  ## Reproduzierbares Staging und Packen
@@ -79,7 +79,13 @@ konkurrierenden Start zurückgewiesen und bleiben an der Spitze der
79
79
  FIFO-Warteschlange. Für diesen normalen Wartestatus erscheint kein
80
80
  `turn.agent_busy`-Fehler.
81
81
 
82
- Version 9.1.490 stellt außerdem die interne Todo-Liste wieder her. Deutsche
82
+ Version 9.1.492 schützt Veröffentlichungen zusätzlich mit einer verpflichtenden
83
+ Metadatenprüfung. Packen und Veröffentlichen brechen ab, wenn Paketversion,
84
+ erster Changelog-Eintrag oder Installationshinweise auseinanderlaufen. Die
85
+ abschließende externe Prüfung vergleicht npm, Paketintegrität, öffentliches
86
+ Update-Manifest und öffentliche Changelog-Seite.
87
+
88
+ Version 9.1.491 stellt außerdem die interne Todo-Liste wieder her. Deutsche
83
89
  Aufgabenlisten-Befehle wählen wieder TodoList statt der getrennten TaskList für
84
90
  Hintergrundprozesse. Lesen, Ersetzen, Aktualisieren und Leeren funktionieren in
85
91
  derselben Sitzung; eine vollständig erledigte Liste wird aus der Anzeige
package/blun.mjs CHANGED
@@ -504027,12 +504027,18 @@ var ChannelQueueDeadlineController = class {
504027
504027
  }
504028
504028
  requestDeliveryAtSafePoint() {
504029
504029
  if (this.retainReleaseWhileDeliveryIsInFlight()) return;
504030
- if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) return;
504030
+ if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) {
504031
+ this.scheduleRetry();
504032
+ return;
504033
+ }
504031
504034
  this.requestDelivery();
504032
504035
  }
504033
504036
  requestDeliveryNow() {
504034
504037
  if (this.retainReleaseWhileDeliveryIsInFlight()) return;
504035
- if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) return;
504038
+ if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) {
504039
+ this.scheduleRetry();
504040
+ return;
504041
+ }
504036
504042
  this.requestDelivery();
504037
504043
  }
504038
504044
  retainReleaseWhileDeliveryIsInFlight() {
@@ -518441,7 +518447,9 @@ var BlunTUI = class {
518441
518447
  else if (directEnvelope !== void 0) enqueueTelegramDirect(this.state.queuedMessages, item);
518442
518448
  else if (addressed) enqueueTelegramAddressed(this.state.queuedMessages, item);
518443
518449
  else this.state.queuedMessages.push(item);
518444
- this.channelQueueDeadline.requestDeliveryNow();
518450
+ const activeTurn = this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle" && this.state.appState.streamingPhase !== "shell";
518451
+ if (directEnvelope !== void 0 && activeTurn) this.releaseNextQueuedMessage();
518452
+ if (this.queueFlushBatchRemaining > 0) this.channelQueueDeadline.requestDeliveryNow();
518445
518453
  this.scheduleQueueDrain();
518446
518454
  this.track("input_queue");
518447
518455
  this.updateQueueDisplay();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.490",
3
+ "version": "9.1.492",
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": {
@@ -9,6 +9,8 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "node --test test/*.test.js",
12
+ "prepack": "node scripts/check-release-metadata.js",
13
+ "release:verify": "node scripts/check-release-metadata.js --external",
12
14
  "postinstall": "node scripts/fix-node-pty-perms.js"
13
15
  },
14
16
  "engines": {
@@ -34,6 +36,7 @@
34
36
  "native/",
35
37
  "release-planned-removals.json",
36
38
  "scripts/check-package-regression.js",
39
+ "scripts/check-release-metadata.js",
37
40
  "scripts/fix-node-pty-perms.js",
38
41
  "standard-skills/",
39
42
  "standard-tools/",
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const DEFAULT_MANIFEST_URL = 'https://chat.blun.ai/blun-code-version.json';
7
+ const DEFAULT_DOCS_URL = 'https://docs.blun.ai/changelog.html';
8
+ const DEFAULT_REGISTRY_URL = 'https://registry.npmjs.org';
9
+ const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
10
+
11
+ function assert(condition, message) {
12
+ if (!condition) throw new Error(message);
13
+ }
14
+
15
+ function readUtf8(filePath) {
16
+ return fs.readFileSync(filePath, 'utf8');
17
+ }
18
+
19
+ function firstChangelogVersion(changelog) {
20
+ return /^##\s+(\d+\.\d+\.\d+)\b/mu.exec(changelog)?.[1] || null;
21
+ }
22
+
23
+ function checkLocalReleaseMetadata(root = path.resolve(__dirname, '..')) {
24
+ const packageJson = JSON.parse(readUtf8(path.join(root, 'package.json')));
25
+ const version = String(packageJson.version || '');
26
+ const packageName = String(packageJson.name || '');
27
+ assert(/^\d+\.\d+\.\d+$/u.test(version), 'RELEASE_VERSION_INVALID');
28
+ assert(packageName.length > 0, 'RELEASE_PACKAGE_NAME_MISSING');
29
+
30
+ const changelogVersion = firstChangelogVersion(readUtf8(path.join(root, 'CHANGELOG.md')));
31
+ assert(changelogVersion === version, `CHANGELOG_VERSION_MISMATCH:${changelogVersion || 'missing'}!=${version}`);
32
+
33
+ const installNeedle = `${packageName}@${version}`;
34
+ for (const fileName of ['README.md', 'LIESMICH.txt']) {
35
+ assert(readUtf8(path.join(root, fileName)).includes(installNeedle), `INSTALL_VERSION_MISMATCH:${fileName}`);
36
+ }
37
+ return { packageName, version };
38
+ }
39
+
40
+ async function fetchLimited(url, kind) {
41
+ const response = await fetch(url, {
42
+ headers: { accept: kind === 'json' ? 'application/json' : 'text/html' },
43
+ redirect: 'follow',
44
+ signal: AbortSignal.timeout(15_000),
45
+ });
46
+ assert(response.ok, `RELEASE_FETCH_FAILED:${response.status}:${url}`);
47
+ const declaredLength = Number(response.headers.get('content-length'));
48
+ assert(!Number.isFinite(declaredLength) || declaredLength <= MAX_RESPONSE_BYTES, `RELEASE_RESPONSE_TOO_LARGE:${url}`);
49
+ const body = await response.text();
50
+ assert(Buffer.byteLength(body, 'utf8') <= MAX_RESPONSE_BYTES, `RELEASE_RESPONSE_TOO_LARGE:${url}`);
51
+ return kind === 'json' ? JSON.parse(body) : body;
52
+ }
53
+
54
+ async function checkExternalReleaseMetadata(local, options = {}) {
55
+ const cacheBust = `cb=${Date.now()}`;
56
+ const registryUrl = options.registryUrl || DEFAULT_REGISTRY_URL;
57
+ const manifestUrl = `${options.manifestUrl || DEFAULT_MANIFEST_URL}?${cacheBust}`;
58
+ const docsUrl = `${options.docsUrl || DEFAULT_DOCS_URL}?${cacheBust}`;
59
+ const encodedName = encodeURIComponent(local.packageName);
60
+ const [tags, metadata, manifest, docs] = await Promise.all([
61
+ fetchLimited(`${registryUrl}/-/package/${encodedName}/dist-tags`, 'json'),
62
+ fetchLimited(`${registryUrl}/${encodedName}/${local.version}`, 'json'),
63
+ fetchLimited(manifestUrl, 'json'),
64
+ fetchLimited(docsUrl, 'html'),
65
+ ]);
66
+
67
+ assert(tags.latest === local.version, `NPM_LATEST_MISMATCH:${tags.latest || 'missing'}!=${local.version}`);
68
+ assert(metadata.version === local.version, `NPM_VERSION_MISMATCH:${metadata.version || 'missing'}!=${local.version}`);
69
+ assert(manifest.name === local.packageName, `MANIFEST_PACKAGE_MISMATCH:${manifest.name || 'missing'}!=${local.packageName}`);
70
+ assert(manifest.latest === local.version, `MANIFEST_VERSION_MISMATCH:${manifest.latest || 'missing'}!=${local.version}`);
71
+ assert(typeof metadata.dist?.integrity === 'string' && metadata.dist.integrity.length > 0, 'NPM_INTEGRITY_MISSING');
72
+ assert(manifest.integrity === metadata.dist.integrity, 'MANIFEST_INTEGRITY_MISMATCH');
73
+ assert(docs.includes(`<title>BLUN King ${local.version} `), `PUBLIC_CHANGELOG_VERSION_MISMATCH:${local.version}`);
74
+ return { ...local, integrity: metadata.dist.integrity };
75
+ }
76
+
77
+ function parseArgs(argv) {
78
+ const external = argv.includes('--external');
79
+ const rootArg = argv.find((arg) => arg.startsWith('--root='));
80
+ return { external, root: rootArg ? path.resolve(rootArg.slice('--root='.length)) : undefined };
81
+ }
82
+
83
+ async function main(argv = process.argv.slice(2)) {
84
+ const options = parseArgs(argv);
85
+ const local = checkLocalReleaseMetadata(options.root);
86
+ const result = options.external ? await checkExternalReleaseMetadata(local) : local;
87
+ process.stdout.write(`release-metadata PASS ${JSON.stringify(result)}\n`);
88
+ return result;
89
+ }
90
+
91
+ if (require.main === module) {
92
+ main().catch((error) => {
93
+ process.stderr.write(`release-metadata BLOCK ${error.message}\n`);
94
+ process.exitCode = 1;
95
+ });
96
+ }
97
+
98
+ module.exports = {
99
+ checkExternalReleaseMetadata,
100
+ checkLocalReleaseMetadata,
101
+ firstChangelogVersion,
102
+ main,
103
+ };