blun-king-cli 9.1.68 → 9.1.70
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 +43 -5
- package/README.md +44 -5
- package/bin/launcher-runtime.js +1 -0
- package/bin/standard-tools-bootstrap.js +43 -6
- package/bin/turn-tool-performance-policy.cjs +4 -0
- package/blun.mjs +8 -8
- package/package.json +1 -1
- package/release-planned-removals.json +1 -1
- package/standard-tools/manifest.json +14 -0
- package/telegram-plugin/dist/bridge.mjs +28 -10
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.
|
|
12
|
+
npm install -g blun-king-cli@9.1.69
|
|
13
13
|
|
|
14
14
|
Start
|
|
15
15
|
-----
|
|
@@ -20,6 +20,26 @@ Start
|
|
|
20
20
|
Beide Startbefehle verwenden dieselbe Version, dasselbe Konto, dasselbe Modell
|
|
21
21
|
und dieselben Befehle.
|
|
22
22
|
|
|
23
|
+
Standard-MCPs und Eingabesteuerung in 9.1.69
|
|
24
|
+
--------------------------------------------
|
|
25
|
+
Beim Start richtet BLUN King agent-browser, blun-language-guard, context7 und
|
|
26
|
+
unter Windows windows-mcp automatisch ein. Erkannte Standardkonfigurationen
|
|
27
|
+
werden aktiviert; eigene, abweichende MCP-Befehle bleiben unverändert.
|
|
28
|
+
|
|
29
|
+
/mcp
|
|
30
|
+
blun tools list
|
|
31
|
+
blun tools enable context7
|
|
32
|
+
|
|
33
|
+
/mcp zeigt den Betriebszustand ohne internen Konfigurationspfad. In der
|
|
34
|
+
Detailansicht bleibt der Pfad für die Fehlersuche verfügbar.
|
|
35
|
+
|
|
36
|
+
Telegram-Nachrichten werden in Eingangsreihenfolge verarbeitet. Im Leerlauf
|
|
37
|
+
startet die Warteschlange selbstständig; während eines Werkzeuglaufs erfolgt
|
|
38
|
+
die Zustellung am nächsten geschützten Übergabepunkt. Strg+C und Esc brechen
|
|
39
|
+
einen aktiven Zug ab, ohne den geschriebenen Entwurf zu löschen. Das gilt auch
|
|
40
|
+
bei Autovervollständigung, Geistervorschlägen, Bash-Eingabe und einer offenen
|
|
41
|
+
Mehrzeileneingabe.
|
|
42
|
+
|
|
23
43
|
Zuverlässiger King-Start
|
|
24
44
|
-----------------------
|
|
25
45
|
Der Windows-Hilfsprozess für private Pfade übernimmt TEMP und TMP aus der
|
|
@@ -65,6 +85,16 @@ Ein neuer /loop ersetzt den bisherigen Loop derselben Sitzung. Dabei bleibt
|
|
|
65
85
|
genau ein gespeicherter Loop aktiv. /loop stop, /loop pause und /loop status
|
|
66
86
|
wirken auch dann sofort, wenn der Agent gerade arbeitet.
|
|
67
87
|
|
|
88
|
+
Wird ein neuer /loop während eines laufenden Zugs aktiviert, wird sein erster
|
|
89
|
+
Auftrag hinter dem aktuellen Zug eingereiht. Er startet danach automatisch; es
|
|
90
|
+
entsteht weder ein zweiter paralleler Zug noch der Fehler turn.agent_busy.
|
|
91
|
+
|
|
92
|
+
Beispiel:
|
|
93
|
+
|
|
94
|
+
/loop 5min Prüfe den Teststand und arbeite am nächsten offenen Punkt weiter.
|
|
95
|
+
|
|
96
|
+
Der erste Lauf beginnt direkt nach dem aktuellen Zug, danach alle fünf Minuten.
|
|
97
|
+
|
|
68
98
|
Eine fällige Wiederholung wird als autonomer Aufwecker eingespeist und nicht
|
|
69
99
|
als neue Nutzernachricht behandelt. Die Statuszeile zeigt den nächsten
|
|
70
100
|
Aufweckzeitpunkt laufend an. Beim Fortsetzen derselben Sitzung wird der
|
|
@@ -134,10 +164,18 @@ Alle Befehle funktionieren identisch mit `king`.
|
|
|
134
164
|
|
|
135
165
|
Medienerzeugung
|
|
136
166
|
---------------
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
167
|
+
Für Medienaufträge bleiben GenerateImage, GenerateVideo, GenerateSpeech und
|
|
168
|
+
GetMedia auch bei schlanker Werkzeugauswahl unmittelbar verfügbar. Nutzer
|
|
169
|
+
müssen weder Werkzeugnamen noch Modell-Prompts kennen. Eine normale Anweisung
|
|
170
|
+
wie „Erzeuge ein realistisches Produktbild einer schwarzen Armbanduhr auf weißem
|
|
171
|
+
Marmor“ oder „Animiere das letzte Bild als ruhige Kamerafahrt von sechs Sekunden“
|
|
172
|
+
genügt. King wählt den passenden Medienweg und kann das asynchrone Ergebnis mit
|
|
173
|
+
GetMedia abrufen.
|
|
174
|
+
|
|
175
|
+
Angehängte Bilder werden weiterhin mit ReadMediaFile gelesen. Bild-, Video- und
|
|
176
|
+
Spracherzeugung laufen asynchron, sodass die Konsole während der Verarbeitung
|
|
177
|
+
nutzbar bleibt. GenerateVideo kann außerdem einen abgeschlossenen Bildauftrag
|
|
178
|
+
oder eine lokale PNG- beziehungsweise JPEG-Datei animieren.
|
|
141
179
|
|
|
142
180
|
Die Medienleiste erscheint nur bei aktiven Medienaufträgen. Sie zeigt
|
|
143
181
|
Warteschlangenplatz, Produktionsphase und Laufzeit sowie nur tatsächlich vom
|
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.
|
|
12
|
+
npm install -g blun-king-cli@9.1.69
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Reproduzierbares Staging und Packen
|
|
@@ -40,6 +40,29 @@ erzeugt `/telegram:access connect` einen einmaligen Code. `/connect CODE` im
|
|
|
40
40
|
gewünschten privaten Chat oder in einer Gruppe speichert Chat und Absender
|
|
41
41
|
intern; der Code verfällt nach zehn Minuten und ist nur einmal verwendbar.
|
|
42
42
|
|
|
43
|
+
## Standard-MCPs und Eingabesteuerung in 9.1.69
|
|
44
|
+
|
|
45
|
+
Beim Start richtet BLUN King `agent-browser`, `blun-language-guard`, `context7`
|
|
46
|
+
und unter Windows `windows-mcp` automatisch ein und aktiviert erkannte
|
|
47
|
+
Standardkonfigurationen wieder. Eigene, abweichende MCP-Befehle bleiben
|
|
48
|
+
unverändert. `/mcp` zeigt den Betriebszustand ohne internen Konfigurationspfad;
|
|
49
|
+
in der Detailansicht bleibt der Pfad für die Fehlersuche verfügbar.
|
|
50
|
+
|
|
51
|
+
Beispiele:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
/mcp
|
|
55
|
+
blun tools list
|
|
56
|
+
blun tools enable context7
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Telegram-Nachrichten werden in Eingangsreihenfolge verarbeitet. Trifft eine
|
|
60
|
+
Nachricht im Leerlauf ein, startet die Warteschlange selbstständig; während
|
|
61
|
+
eines Werkzeuglaufs wird sie am nächsten geschützten Übergabepunkt eingefügt.
|
|
62
|
+
`Strg+C` und `Esc` brechen einen aktiven Zug zuverlässig ab, ohne den bereits
|
|
63
|
+
geschriebenen Entwurf zu löschen. Das gilt auch bei Autovervollständigung,
|
|
64
|
+
Geistervorschlägen, Bash-Eingabe und einer noch offenen Mehrzeileneingabe.
|
|
65
|
+
|
|
43
66
|
## Zuverlässiger King-Start
|
|
44
67
|
|
|
45
68
|
Der Windows-Hilfsprozess für private Pfade übernimmt `TEMP` und `TMP` aus der
|
|
@@ -85,6 +108,14 @@ genau ein gespeicherter Loop aktiv; der neue Auftrag, das neue Intervall und
|
|
|
85
108
|
der neue Startzeitpunkt gelten vollständig. `/loop stop`, `/loop pause` und
|
|
86
109
|
`/loop status` wirken auch dann sofort, wenn der Agent gerade arbeitet.
|
|
87
110
|
|
|
111
|
+
Wird ein neuer `/loop` während eines laufenden Zugs aktiviert, wird sein erster
|
|
112
|
+
Auftrag hinter dem aktuellen Zug eingereiht. Er startet danach automatisch; es
|
|
113
|
+
entsteht weder ein zweiter paralleler Zug noch der Fehler `turn.agent_busy`.
|
|
114
|
+
|
|
115
|
+
Beispiel: `/loop 5min Prüfe den Teststand und arbeite am nächsten offenen Punkt
|
|
116
|
+
weiter.` führt den ersten Lauf direkt nach dem aktuellen Zug aus und danach alle
|
|
117
|
+
fünf Minuten.
|
|
118
|
+
|
|
88
119
|
Eine fällige Wiederholung wird als autonomer Aufwecker eingespeist und nicht
|
|
89
120
|
als neue Nutzernachricht behandelt. Die Statuszeile zeigt den nächsten
|
|
90
121
|
Aufweckzeitpunkt laufend an. Beim Fortsetzen derselben Sitzung wird der
|
|
@@ -161,10 +192,18 @@ Sie stehen unter `blun` und `king` identisch zur Verfügung.
|
|
|
161
192
|
|
|
162
193
|
## Medienerzeugung
|
|
163
194
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
195
|
+
Für Medienaufträge bleiben `GenerateImage`, `GenerateVideo`, `GenerateSpeech`
|
|
196
|
+
und `GetMedia` auch bei schlanker Werkzeugauswahl unmittelbar verfügbar. Nutzer
|
|
197
|
+
müssen weder Werkzeugnamen noch Modell-Prompts kennen. Eine normale Anweisung
|
|
198
|
+
wie „Erzeuge ein realistisches Produktbild einer schwarzen Armbanduhr auf weißem
|
|
199
|
+
Marmor“ oder „Animiere das letzte Bild als ruhige Kamerafahrt von sechs Sekunden“
|
|
200
|
+
genügt. King wählt den passenden Medienweg und kann das asynchrone Ergebnis mit
|
|
201
|
+
`GetMedia` abrufen.
|
|
202
|
+
|
|
203
|
+
Angehängte Bilder werden weiterhin mit `ReadMediaFile` gelesen. Bild-, Video-
|
|
204
|
+
und Spracherzeugung laufen asynchron, sodass die Konsole während der Verarbeitung
|
|
205
|
+
nutzbar bleibt. `GenerateVideo` kann außerdem einen abgeschlossenen Bildauftrag
|
|
206
|
+
oder eine lokale PNG- beziehungsweise JPEG-Datei animieren.
|
|
168
207
|
|
|
169
208
|
Die Medienleiste erscheint nur bei aktiven Medienaufträgen. Sie zeigt
|
|
170
209
|
Warteschlangenplatz, Produktionsphase und Laufzeit sowie nur tatsächlich vom
|
package/bin/launcher-runtime.js
CHANGED
|
@@ -31,6 +31,9 @@ function readCatalogue(packageRoot) {
|
|
|
31
31
|
|| !tool.platforms.every((platform) => platform === 'darwin' || platform === 'win32'))) {
|
|
32
32
|
throw new Error(`Ungueltige Standard-Tool-Plattform: ${name}`);
|
|
33
33
|
}
|
|
34
|
+
if (tool.autoEnable !== undefined && typeof tool.autoEnable !== 'boolean') {
|
|
35
|
+
throw new Error(`Ungueltiger Standard-Tool-Autostart: ${name}`);
|
|
36
|
+
}
|
|
34
37
|
if (tool.owner === 'user-mcp'
|
|
35
38
|
&& (!isObject(tool.config) || typeof tool.config.enabled !== 'boolean')) {
|
|
36
39
|
throw new Error(`Standard-Tool braucht einen Aktivierungszustand: ${name}`);
|
|
@@ -81,16 +84,41 @@ function sameStringArray(left, right) {
|
|
|
81
84
|
&& left.every((value, index) => value === right[index]);
|
|
82
85
|
}
|
|
83
86
|
|
|
84
|
-
function recognizedBundledServer(current, expected) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
function recognizedBundledServer(name, current, expected) {
|
|
88
|
+
if (!isObject(current)) return false;
|
|
89
|
+
const exact = current.transport === expected.transport
|
|
87
90
|
&& current.command === expected.command
|
|
88
91
|
&& sameStringArray(current.args, expected.args);
|
|
92
|
+
if (exact) return true;
|
|
93
|
+
return name === 'context7'
|
|
94
|
+
&& current.transport === 'stdio'
|
|
95
|
+
&& current.command === 'npx'
|
|
96
|
+
&& Array.isArray(current.args)
|
|
97
|
+
&& current.args[0] === '-y'
|
|
98
|
+
&& /^@upstash\/context7-mcp(?:@[^\s]+)?$/u.test(current.args[1] ?? '');
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
function migrateBundledTimeouts(name, current, expected) {
|
|
92
|
-
if (!recognizedBundledServer(current, expected)) return false;
|
|
102
|
+
if (!recognizedBundledServer(name, current, expected)) return false;
|
|
93
103
|
let changed = false;
|
|
104
|
+
if (name === 'context7') {
|
|
105
|
+
if (expected.blunExplicitlyEnabled === true) {
|
|
106
|
+
if (current.enabled !== true) {
|
|
107
|
+
current.enabled = true;
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
if (current.blunExplicitlyEnabled !== true) {
|
|
111
|
+
current.blunExplicitlyEnabled = true;
|
|
112
|
+
changed = true;
|
|
113
|
+
}
|
|
114
|
+
} else if (current.blunExplicitlyEnabled !== true && current.enabled !== false) {
|
|
115
|
+
current.enabled = false;
|
|
116
|
+
changed = true;
|
|
117
|
+
}
|
|
118
|
+
} else if (current.enabled === false) {
|
|
119
|
+
current.enabled = true;
|
|
120
|
+
changed = true;
|
|
121
|
+
}
|
|
94
122
|
if (name === 'agent-browser') {
|
|
95
123
|
if (current.startupTimeoutMs === 30_000) {
|
|
96
124
|
current.startupTimeoutMs = expected.startupTimeoutMs;
|
|
@@ -123,9 +151,16 @@ function writeMcpDocument(configPath, document) {
|
|
|
123
151
|
}
|
|
124
152
|
}
|
|
125
153
|
|
|
126
|
-
function bundledToolConfig(name, tool, {
|
|
154
|
+
function bundledToolConfig(name, tool, {
|
|
155
|
+
packageRoot,
|
|
156
|
+
blunDir,
|
|
157
|
+
platform,
|
|
158
|
+
env,
|
|
159
|
+
forceEnable,
|
|
160
|
+
}) {
|
|
127
161
|
const config = structuredClone(tool.config);
|
|
128
|
-
config.enabled =
|
|
162
|
+
config.enabled = forceEnable || tool.autoEnable !== false;
|
|
163
|
+
if (forceEnable && tool.autoEnable === false) config.blunExplicitlyEnabled = true;
|
|
129
164
|
if (name === 'blun-language-guard') {
|
|
130
165
|
config.command = platform === 'win32' ? 'python' : 'python3';
|
|
131
166
|
config.args = [
|
|
@@ -174,6 +209,7 @@ function seedStandardTools({
|
|
|
174
209
|
names,
|
|
175
210
|
platform = process.platform,
|
|
176
211
|
env = process.env,
|
|
212
|
+
forceEnable = false,
|
|
177
213
|
}) {
|
|
178
214
|
const catalogue = readCatalogue(packageRoot);
|
|
179
215
|
if (!Array.isArray(names) || names.length === 0) {
|
|
@@ -204,6 +240,7 @@ function seedStandardTools({
|
|
|
204
240
|
blunDir,
|
|
205
241
|
platform,
|
|
206
242
|
env,
|
|
243
|
+
forceEnable,
|
|
207
244
|
});
|
|
208
245
|
if (Object.hasOwn(servers, name)) {
|
|
209
246
|
if (migrateBundledTimeouts(name, servers[name], expected)) updated.push(name);
|
|
@@ -18,6 +18,10 @@ const CORE_TOOL_NAMES = Object.freeze([
|
|
|
18
18
|
'ReadMediaFile',
|
|
19
19
|
'TaskOutput',
|
|
20
20
|
'Skill',
|
|
21
|
+
'GenerateImage',
|
|
22
|
+
'GenerateVideo',
|
|
23
|
+
'GenerateSpeech',
|
|
24
|
+
'GetMedia',
|
|
21
25
|
'mcp__plugin-telegram_telegram__reply',
|
|
22
26
|
'mcp__plugin-telegram_telegram__react',
|
|
23
27
|
'mcp__plugin-telegram_telegram__edit_message',
|
package/blun.mjs
CHANGED
|
@@ -421036,7 +421036,8 @@ async function handleLoopCommand(host, args) {
|
|
|
421036
421036
|
host.setAppState?.({ loop });
|
|
421037
421037
|
host.track("loop_start", { interval: loop.interval });
|
|
421038
421038
|
host.showStatus(`/loop ${loop.status}`);
|
|
421039
|
-
host.
|
|
421039
|
+
if (isStreaming(host) || host.state.appState.isCompacting) host.enqueueNormalUserInput(loop.prompt);
|
|
421040
|
+
else host.sendNormalUserInput(loop.prompt);
|
|
421040
421041
|
return;
|
|
421041
421042
|
}
|
|
421042
421043
|
case "pause": {
|
|
@@ -421937,8 +421938,6 @@ var McpManagerComponent = class extends Container {
|
|
|
421937
421938
|
const name = selected ? currentTheme.boldFg("primary", server.name) : currentTheme.fg("text", server.name);
|
|
421938
421939
|
const status = currentTheme.fg(statusTone(server.status), statusLabel$2(server.status));
|
|
421939
421940
|
lines.push(` ${pointer} ${name} ${status} ${currentTheme.fg("textMuted", toolCount(server))}`);
|
|
421940
|
-
const origin = originDescription(server);
|
|
421941
|
-
if (origin !== void 0) lines.push(currentTheme.fg("textMuted", ` ${origin}`));
|
|
421942
421941
|
}
|
|
421943
421942
|
if (view.items.length === 0) lines.push(currentTheme.fg("textMuted", ` ${uiText("common.noMatches")}`));
|
|
421944
421943
|
lines.push("");
|
|
@@ -422055,10 +422054,6 @@ function groupLabel(group) {
|
|
|
422055
422054
|
function sourceLabel(group) {
|
|
422056
422055
|
return uiText(`mcp.source.${group}`);
|
|
422057
422056
|
}
|
|
422058
|
-
function originDescription(server) {
|
|
422059
|
-
if (server.source === "plugin") return uiText("mcp.origin.plugin", { id: server.pluginId ?? uiText("mcp.unknown") });
|
|
422060
|
-
return server.configPath === void 0 ? void 0 : sanitizeMcpDisplayText(server.configPath);
|
|
422061
|
-
}
|
|
422062
422057
|
function detailRows(server) {
|
|
422063
422058
|
const rows = [
|
|
422064
422059
|
[uiText("mcp.detail.status"), statusLabel$2(server.status)],
|
|
@@ -514662,7 +514657,6 @@ var BlunTUI = class {
|
|
|
514662
514657
|
...envelope.meta["image_path"] !== void 0 ? { channelImagePath: envelope.meta["image_path"] } : {}
|
|
514663
514658
|
});
|
|
514664
514659
|
this.syncChannelQueueDeadline();
|
|
514665
|
-
this.channelQueueDeadline.requestDeliveryNow();
|
|
514666
514660
|
this.scheduleQueueDrain();
|
|
514667
514661
|
this.track("input_queue");
|
|
514668
514662
|
this.updateQueueDisplay();
|
|
@@ -515021,6 +515015,12 @@ var BlunTUI = class {
|
|
|
515021
515015
|
this.updateQueueDisplay();
|
|
515022
515016
|
this.state.ui.requestRender();
|
|
515023
515017
|
}
|
|
515018
|
+
enqueueNormalUserInput(text) {
|
|
515019
|
+
this.enqueueMessage(text);
|
|
515020
|
+
this.updateQueueDisplay();
|
|
515021
|
+
this.scheduleQueueDrain();
|
|
515022
|
+
this.state.ui.requestRender();
|
|
515023
|
+
}
|
|
515024
515024
|
beginSessionRequest() {
|
|
515025
515025
|
this.streamingUI.setTurnId(void 0);
|
|
515026
515026
|
this.streamingUI.resetLiveText();
|
package/package.json
CHANGED
|
@@ -31,6 +31,20 @@
|
|
|
31
31
|
"toolTimeoutMs": 120000
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
|
+
"context7": {
|
|
35
|
+
"owner": "user-mcp",
|
|
36
|
+
"version": "latest",
|
|
37
|
+
"autoEnable": false,
|
|
38
|
+
"detectTokens": ["context7", "@upstash/context7-mcp"],
|
|
39
|
+
"config": {
|
|
40
|
+
"transport": "stdio",
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@upstash/context7-mcp@latest"],
|
|
43
|
+
"enabled": false,
|
|
44
|
+
"startupTimeoutMs": 40000,
|
|
45
|
+
"toolTimeoutMs": 120000
|
|
46
|
+
}
|
|
47
|
+
},
|
|
34
48
|
"telegram": {
|
|
35
49
|
"owner": "managed-plugin",
|
|
36
50
|
"version": "bundled",
|
|
@@ -4372,21 +4372,36 @@ var KingSession = class {
|
|
|
4372
4372
|
* orphan means permanent 409 Conflict), pairing-approval confirmations,
|
|
4373
4373
|
* and the backoff polling loop.
|
|
4374
4374
|
*/
|
|
4375
|
-
/**
|
|
4375
|
+
/** Atomically claim the token poller without interrupting a live owner. */
|
|
4376
4376
|
function claimPollerPid() {
|
|
4377
4377
|
mkdirSync(stateDir(), {
|
|
4378
4378
|
recursive: true,
|
|
4379
4379
|
mode: 448
|
|
4380
4380
|
});
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4381
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
4382
|
+
try {
|
|
4383
|
+
writeFileSync(pidFile(), String(process.pid), { flag: "wx" });
|
|
4384
|
+
return true;
|
|
4385
|
+
} catch (error) {
|
|
4386
|
+
if (error?.code !== "EEXIST") throw error;
|
|
4387
4387
|
}
|
|
4388
|
-
|
|
4389
|
-
|
|
4388
|
+
let ownerPid;
|
|
4389
|
+
try {
|
|
4390
|
+
ownerPid = parseInt(readFileSync(pidFile(), "utf8"), 10);
|
|
4391
|
+
} catch {}
|
|
4392
|
+
if (ownerPid === process.pid) return true;
|
|
4393
|
+
if (ownerPid !== void 0 && ownerPid > 1) try {
|
|
4394
|
+
process.kill(ownerPid, 0);
|
|
4395
|
+
process.stderr.write(`telegram channel: live poller pid=${ownerPid} already owns the bot token\n`);
|
|
4396
|
+
return false;
|
|
4397
|
+
} catch {}
|
|
4398
|
+
try {
|
|
4399
|
+
rmSync(pidFile());
|
|
4400
|
+
} catch {
|
|
4401
|
+
return false;
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
return false;
|
|
4390
4405
|
}
|
|
4391
4406
|
function releasePollerPid() {
|
|
4392
4407
|
try {
|
|
@@ -4546,7 +4561,10 @@ process.on("uncaughtException", (err) => {
|
|
|
4546
4561
|
});
|
|
4547
4562
|
ensureStateDir();
|
|
4548
4563
|
rotateStaleTuiQueue();
|
|
4549
|
-
claimPollerPid()
|
|
4564
|
+
if (!claimPollerPid()) {
|
|
4565
|
+
process.stderr.write("telegram channel: another live poller owns the bot token; exiting\n");
|
|
4566
|
+
process.exit(0);
|
|
4567
|
+
}
|
|
4550
4568
|
const bot = new import_out.Bot(TOKEN);
|
|
4551
4569
|
let botUsername = "";
|
|
4552
4570
|
const session = new KingSession(KING_ENTRY, (msg) => {
|