blun-king-cli 9.1.585 → 9.1.586
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 +6 -0
- package/blun.mjs +99 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## 9.1.586 - 2026-09-09
|
|
2
|
+
|
|
3
|
+
- Fix Telegram receiver startup on Windows when an old bridge PID has been reused by an unrelated process. Preserve uncertain process ownership and never stop that unrelated process.
|
|
4
|
+
- Keep context compaction, model settings, conversation history, and existing Telegram delivery behavior unchanged.
|
|
5
|
+
|
|
6
|
+
|
|
1
7
|
## 9.1.585 - 2026-09-08
|
|
2
8
|
|
|
3
9
|
- Managed WebSearch validates result envelopes and source rows even when optional search status metadata is absent.
|
package/blun.mjs
CHANGED
|
@@ -422277,7 +422277,41 @@ function resolveTelegramMcpEntry() {
|
|
|
422277
422277
|
];
|
|
422278
422278
|
for (const candidate of candidates) if (candidate !== void 0 && existsSync(candidate)) return resolveKnownTelegramMcp(candidate, { explicitOverride: candidate === process.env["BLUN_TELEGRAM_MCP_SERVER"] });
|
|
422279
422279
|
}
|
|
422280
|
+
import { fstatSync as __blunTelegramPidFstatSync } from "node:fs";
|
|
422281
|
+
"use strict";
|
|
422282
|
+
const PROCESS_START_LOOKUP_TIMEOUT_MS = 1500;
|
|
422283
|
+
const PID_CLAIM_TIME_TOLERANCE_MS = 1000;
|
|
422284
|
+
function readNonBridgeProcessStartedAt(pid) {
|
|
422285
|
+
if (process.platform !== 'win32' || !Number.isSafeInteger(pid) || pid <= 1)
|
|
422286
|
+
return undefined;
|
|
422287
|
+
try {
|
|
422288
|
+
const output = execFileSync('powershell.exe', [
|
|
422289
|
+
'-NoProfile', '-NonInteractive', '-Command',
|
|
422290
|
+
`$ErrorActionPreference='Stop'; $p=Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}'; ` +
|
|
422291
|
+
// A recognizable bridge is preserved even after a wall-clock correction.
|
|
422292
|
+
`if($null -ne $p -and -not [string]::IsNullOrWhiteSpace($p.CommandLine) -and $p.CommandLine -notmatch 'bridge\\.mjs'){` +
|
|
422293
|
+
`([DateTimeOffset]$p.CreationDate.ToUniversalTime()).ToUnixTimeMilliseconds()}`,
|
|
422294
|
+
], {
|
|
422295
|
+
encoding: 'utf8',
|
|
422296
|
+
windowsHide: true,
|
|
422297
|
+
timeout: PROCESS_START_LOOKUP_TIMEOUT_MS,
|
|
422298
|
+
maxBuffer: 4096,
|
|
422299
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
422300
|
+
}).trim();
|
|
422301
|
+
if (!/^\d+$/.test(output))
|
|
422302
|
+
return undefined;
|
|
422303
|
+
const startedAt = Number(output);
|
|
422304
|
+
return Number.isSafeInteger(startedAt) && startedAt > 0 ? startedAt : undefined;
|
|
422305
|
+
}
|
|
422306
|
+
catch {
|
|
422307
|
+
return undefined;
|
|
422308
|
+
}
|
|
422309
|
+
}
|
|
422310
|
+
|
|
422280
422311
|
var TelegramChannelController = class {
|
|
422312
|
+
bridgeClaimUncertain = false;
|
|
422313
|
+
readProcessStartedAt;
|
|
422314
|
+
|
|
422281
422315
|
host;
|
|
422282
422316
|
dir;
|
|
422283
422317
|
heartbeatTimer;
|
|
@@ -422343,7 +422377,9 @@ var TelegramChannelController = class {
|
|
|
422343
422377
|
return false;
|
|
422344
422378
|
}
|
|
422345
422379
|
});
|
|
422346
|
-
|
|
422380
|
+
|
|
422381
|
+
this.readProcessStartedAt = options.readProcessStartedAt ?? readNonBridgeProcessStartedAt;
|
|
422382
|
+
}
|
|
422347
422383
|
get leaseFile() {
|
|
422348
422384
|
return join(this.dir, "tui.pid");
|
|
422349
422385
|
}
|
|
@@ -422466,11 +422502,68 @@ var TelegramChannelController = class {
|
|
|
422466
422502
|
this.handoffTimer.unref();
|
|
422467
422503
|
}
|
|
422468
422504
|
liveBridgePid() {
|
|
422469
|
-
|
|
422470
|
-
|
|
422471
|
-
|
|
422472
|
-
|
|
422473
|
-
|
|
422505
|
+
if (this.bridgeClaimUncertain)
|
|
422506
|
+
return null;
|
|
422507
|
+
let pid;
|
|
422508
|
+
let claim;
|
|
422509
|
+
let stats;
|
|
422510
|
+
try {
|
|
422511
|
+
const fd = openSync(this.botPidFile, 'r');
|
|
422512
|
+
try {
|
|
422513
|
+
claim = readFileSync(fd, 'utf8');
|
|
422514
|
+
stats = __blunTelegramPidFstatSync(fd);
|
|
422515
|
+
}
|
|
422516
|
+
finally {
|
|
422517
|
+
closeSync(fd);
|
|
422518
|
+
}
|
|
422519
|
+
pid = parseInt(claim, 10);
|
|
422520
|
+
if (!Number.isInteger(pid) || pid <= 1)
|
|
422521
|
+
return null;
|
|
422522
|
+
if (!this.isProcessAlive(pid))
|
|
422523
|
+
return undefined;
|
|
422524
|
+
}
|
|
422525
|
+
catch (error) {
|
|
422526
|
+
// Only an absent claim proves that reading it did not hide an owner.
|
|
422527
|
+
return error.code === 'ENOENT' ? undefined : null;
|
|
422528
|
+
}
|
|
422529
|
+
try {
|
|
422530
|
+
const startedAt = this.readProcessStartedAt(pid);
|
|
422531
|
+
if (startedAt !== undefined && Number.isFinite(startedAt)
|
|
422532
|
+
&& startedAt > stats.mtimeMs + PID_CLAIM_TIME_TOLERANCE_MS
|
|
422533
|
+
&& this.ownsChannel() && this.retireReusedBridgePid(claim, stats))
|
|
422534
|
+
return undefined;
|
|
422535
|
+
}
|
|
422536
|
+
catch {
|
|
422537
|
+
// A failed identity or archive lookup must not launch a second poller.
|
|
422538
|
+
}
|
|
422539
|
+
return pid;
|
|
422540
|
+
}
|
|
422541
|
+
retireReusedBridgePid(claim, original) {
|
|
422542
|
+
const matches = (file) => {
|
|
422543
|
+
const current = lstatSync(file);
|
|
422544
|
+
return current.isFile() && current.dev === original.dev && current.ino === original.ino
|
|
422545
|
+
&& current.size === original.size && current.mtimeMs === original.mtimeMs
|
|
422546
|
+
&& readFileSync(file, 'utf8') === claim;
|
|
422547
|
+
};
|
|
422548
|
+
if (!matches(this.botPidFile))
|
|
422549
|
+
return false;
|
|
422550
|
+
const retired = join(this.dir, `bot.pid.stale-${randomUUID()}`);
|
|
422551
|
+
renameSync(this.botPidFile, retired);
|
|
422552
|
+
try {
|
|
422553
|
+
if (matches(retired))
|
|
422554
|
+
return true;
|
|
422555
|
+
}
|
|
422556
|
+
catch {
|
|
422557
|
+
// Restore the name if the moved claim cannot be verified.
|
|
422558
|
+
}
|
|
422559
|
+
this.bridgeClaimUncertain = true;
|
|
422560
|
+
// Do not overwrite a newer claim if another writer won the rename window.
|
|
422561
|
+
try {
|
|
422562
|
+
linkSync(retired, this.botPidFile);
|
|
422563
|
+
}
|
|
422564
|
+
catch { /* A current claim wins. */ }
|
|
422565
|
+
return false;
|
|
422566
|
+
}
|
|
422474
422567
|
releaseOwnership() {
|
|
422475
422568
|
try {
|
|
422476
422569
|
if (this.readOwner()?.ownerId === this.ownerId) rmSync(this.ownerFile);
|