blun-king-cli 9.1.69 → 9.1.71
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 +30 -9
- package/README.md +29 -10
- package/bin/launcher-runtime.js +1 -0
- package/bin/standard-tools-bootstrap.js +29 -3
- package/bin/turn-tool-performance-policy.cjs +4 -0
- package/blun.mjs +8 -1
- package/package.json +1 -1
- package/standard-tools/manifest.json +1 -0
- package/telegram-plugin/dist/bridge.mjs +28 -10
package/LIESMICH.txt
CHANGED
|
@@ -20,11 +20,14 @@ Start
|
|
|
20
20
|
Beide Startbefehle verwenden dieselbe Version, dasselbe Konto, dasselbe Modell
|
|
21
21
|
und dieselben Befehle.
|
|
22
22
|
|
|
23
|
-
Standard-MCPs und Eingabesteuerung
|
|
24
|
-
|
|
25
|
-
Beim Start richtet BLUN King agent-browser
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
Standard-MCPs und Eingabesteuerung
|
|
24
|
+
---------------------------------
|
|
25
|
+
Beim Start richtet BLUN King `agent-browser`, `blun-language-guard` und unter
|
|
26
|
+
Windows `windows-mcp` automatisch ein und aktiviert erkannte
|
|
27
|
+
Standardkonfigurationen. Context7 wird eingerichtet, bleibt aber standardmäßig
|
|
28
|
+
deaktiviert, weil sein Start hängen bleiben kann. Mit
|
|
29
|
+
`blun tools enable context7` lässt es sich ausdrücklich aktivieren. Eigene,
|
|
30
|
+
abweichende MCP-Befehle bleiben unverändert.
|
|
28
31
|
|
|
29
32
|
/mcp
|
|
30
33
|
blun tools list
|
|
@@ -85,6 +88,16 @@ Ein neuer /loop ersetzt den bisherigen Loop derselben Sitzung. Dabei bleibt
|
|
|
85
88
|
genau ein gespeicherter Loop aktiv. /loop stop, /loop pause und /loop status
|
|
86
89
|
wirken auch dann sofort, wenn der Agent gerade arbeitet.
|
|
87
90
|
|
|
91
|
+
Wird ein neuer /loop während eines laufenden Zugs aktiviert, wird sein erster
|
|
92
|
+
Auftrag hinter dem aktuellen Zug eingereiht. Er startet danach automatisch; es
|
|
93
|
+
entsteht weder ein zweiter paralleler Zug noch der Fehler turn.agent_busy.
|
|
94
|
+
|
|
95
|
+
Beispiel:
|
|
96
|
+
|
|
97
|
+
/loop 5min Prüfe den Teststand und arbeite am nächsten offenen Punkt weiter.
|
|
98
|
+
|
|
99
|
+
Der erste Lauf beginnt direkt nach dem aktuellen Zug, danach alle fünf Minuten.
|
|
100
|
+
|
|
88
101
|
Eine fällige Wiederholung wird als autonomer Aufwecker eingespeist und nicht
|
|
89
102
|
als neue Nutzernachricht behandelt. Die Statuszeile zeigt den nächsten
|
|
90
103
|
Aufweckzeitpunkt laufend an. Beim Fortsetzen derselben Sitzung wird der
|
|
@@ -154,10 +167,18 @@ Alle Befehle funktionieren identisch mit `king`.
|
|
|
154
167
|
|
|
155
168
|
Medienerzeugung
|
|
156
169
|
---------------
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
170
|
+
Für Medienaufträge bleiben GenerateImage, GenerateVideo, GenerateSpeech und
|
|
171
|
+
GetMedia auch bei schlanker Werkzeugauswahl unmittelbar verfügbar. Nutzer
|
|
172
|
+
müssen weder Werkzeugnamen noch Modell-Prompts kennen. Eine normale Anweisung
|
|
173
|
+
wie „Erzeuge ein realistisches Produktbild einer schwarzen Armbanduhr auf weißem
|
|
174
|
+
Marmor“ oder „Animiere das letzte Bild als ruhige Kamerafahrt von sechs Sekunden“
|
|
175
|
+
genügt. King wählt den passenden Medienweg und kann das asynchrone Ergebnis mit
|
|
176
|
+
GetMedia abrufen.
|
|
177
|
+
|
|
178
|
+
Angehängte Bilder werden weiterhin mit ReadMediaFile gelesen. Bild-, Video- und
|
|
179
|
+
Spracherzeugung laufen asynchron, sodass die Konsole während der Verarbeitung
|
|
180
|
+
nutzbar bleibt. GenerateVideo kann außerdem einen abgeschlossenen Bildauftrag
|
|
181
|
+
oder eine lokale PNG- beziehungsweise JPEG-Datei animieren.
|
|
161
182
|
|
|
162
183
|
Die Medienleiste erscheint nur bei aktiven Medienaufträgen. Sie zeigt
|
|
163
184
|
Warteschlangenplatz, Produktionsphase und Laufzeit sowie nur tatsächlich vom
|
package/README.md
CHANGED
|
@@ -40,13 +40,16 @@ 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
|
|
43
|
+
## Standard-MCPs und Eingabesteuerung
|
|
44
44
|
|
|
45
|
-
Beim Start richtet BLUN King `agent-browser`, `blun-language-guard
|
|
46
|
-
|
|
47
|
-
Standardkonfigurationen
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
Beim Start richtet BLUN King `agent-browser`, `blun-language-guard` und unter
|
|
46
|
+
Windows `windows-mcp` automatisch ein und aktiviert erkannte
|
|
47
|
+
Standardkonfigurationen. Context7 wird eingerichtet, bleibt aber standardmäßig
|
|
48
|
+
deaktiviert, weil sein Start hängen bleiben kann. Mit
|
|
49
|
+
`blun tools enable context7` lässt es sich ausdrücklich aktivieren. Eigene,
|
|
50
|
+
abweichende MCP-Befehle bleiben unverändert. `/mcp` zeigt den Betriebszustand
|
|
51
|
+
ohne internen Konfigurationspfad; in der Detailansicht bleibt der Pfad für die
|
|
52
|
+
Fehlersuche verfügbar.
|
|
50
53
|
|
|
51
54
|
Beispiele:
|
|
52
55
|
|
|
@@ -108,6 +111,14 @@ genau ein gespeicherter Loop aktiv; der neue Auftrag, das neue Intervall und
|
|
|
108
111
|
der neue Startzeitpunkt gelten vollständig. `/loop stop`, `/loop pause` und
|
|
109
112
|
`/loop status` wirken auch dann sofort, wenn der Agent gerade arbeitet.
|
|
110
113
|
|
|
114
|
+
Wird ein neuer `/loop` während eines laufenden Zugs aktiviert, wird sein erster
|
|
115
|
+
Auftrag hinter dem aktuellen Zug eingereiht. Er startet danach automatisch; es
|
|
116
|
+
entsteht weder ein zweiter paralleler Zug noch der Fehler `turn.agent_busy`.
|
|
117
|
+
|
|
118
|
+
Beispiel: `/loop 5min Prüfe den Teststand und arbeite am nächsten offenen Punkt
|
|
119
|
+
weiter.` führt den ersten Lauf direkt nach dem aktuellen Zug aus und danach alle
|
|
120
|
+
fünf Minuten.
|
|
121
|
+
|
|
111
122
|
Eine fällige Wiederholung wird als autonomer Aufwecker eingespeist und nicht
|
|
112
123
|
als neue Nutzernachricht behandelt. Die Statuszeile zeigt den nächsten
|
|
113
124
|
Aufweckzeitpunkt laufend an. Beim Fortsetzen derselben Sitzung wird der
|
|
@@ -184,10 +195,18 @@ Sie stehen unter `blun` und `king` identisch zur Verfügung.
|
|
|
184
195
|
|
|
185
196
|
## Medienerzeugung
|
|
186
197
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
Für Medienaufträge bleiben `GenerateImage`, `GenerateVideo`, `GenerateSpeech`
|
|
199
|
+
und `GetMedia` auch bei schlanker Werkzeugauswahl unmittelbar verfügbar. Nutzer
|
|
200
|
+
müssen weder Werkzeugnamen noch Modell-Prompts kennen. Eine normale Anweisung
|
|
201
|
+
wie „Erzeuge ein realistisches Produktbild einer schwarzen Armbanduhr auf weißem
|
|
202
|
+
Marmor“ oder „Animiere das letzte Bild als ruhige Kamerafahrt von sechs Sekunden“
|
|
203
|
+
genügt. King wählt den passenden Medienweg und kann das asynchrone Ergebnis mit
|
|
204
|
+
`GetMedia` abrufen.
|
|
205
|
+
|
|
206
|
+
Angehängte Bilder werden weiterhin mit `ReadMediaFile` gelesen. Bild-, Video-
|
|
207
|
+
und Spracherzeugung laufen asynchron, sodass die Konsole während der Verarbeitung
|
|
208
|
+
nutzbar bleibt. `GenerateVideo` kann außerdem einen abgeschlossenen Bildauftrag
|
|
209
|
+
oder eine lokale PNG- beziehungsweise JPEG-Datei animieren.
|
|
191
210
|
|
|
192
211
|
Die Medienleiste erscheint nur bei aktiven Medienaufträgen. Sie zeigt
|
|
193
212
|
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}`);
|
|
@@ -98,7 +101,21 @@ function recognizedBundledServer(name, current, expected) {
|
|
|
98
101
|
function migrateBundledTimeouts(name, current, expected) {
|
|
99
102
|
if (!recognizedBundledServer(name, current, expected)) return false;
|
|
100
103
|
let changed = false;
|
|
101
|
-
if (
|
|
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) {
|
|
102
119
|
current.enabled = true;
|
|
103
120
|
changed = true;
|
|
104
121
|
}
|
|
@@ -134,9 +151,16 @@ function writeMcpDocument(configPath, document) {
|
|
|
134
151
|
}
|
|
135
152
|
}
|
|
136
153
|
|
|
137
|
-
function bundledToolConfig(name, tool, {
|
|
154
|
+
function bundledToolConfig(name, tool, {
|
|
155
|
+
packageRoot,
|
|
156
|
+
blunDir,
|
|
157
|
+
platform,
|
|
158
|
+
env,
|
|
159
|
+
forceEnable,
|
|
160
|
+
}) {
|
|
138
161
|
const config = structuredClone(tool.config);
|
|
139
|
-
config.enabled =
|
|
162
|
+
config.enabled = forceEnable || tool.autoEnable !== false;
|
|
163
|
+
if (forceEnable && tool.autoEnable === false) config.blunExplicitlyEnabled = true;
|
|
140
164
|
if (name === 'blun-language-guard') {
|
|
141
165
|
config.command = platform === 'win32' ? 'python' : 'python3';
|
|
142
166
|
config.args = [
|
|
@@ -185,6 +209,7 @@ function seedStandardTools({
|
|
|
185
209
|
names,
|
|
186
210
|
platform = process.platform,
|
|
187
211
|
env = process.env,
|
|
212
|
+
forceEnable = false,
|
|
188
213
|
}) {
|
|
189
214
|
const catalogue = readCatalogue(packageRoot);
|
|
190
215
|
if (!Array.isArray(names) || names.length === 0) {
|
|
@@ -215,6 +240,7 @@ function seedStandardTools({
|
|
|
215
240
|
blunDir,
|
|
216
241
|
platform,
|
|
217
242
|
env,
|
|
243
|
+
forceEnable,
|
|
218
244
|
});
|
|
219
245
|
if (Object.hasOwn(servers, name)) {
|
|
220
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": {
|
|
@@ -515014,6 +515015,12 @@ var BlunTUI = class {
|
|
|
515014
515015
|
this.updateQueueDisplay();
|
|
515015
515016
|
this.state.ui.requestRender();
|
|
515016
515017
|
}
|
|
515018
|
+
enqueueNormalUserInput(text) {
|
|
515019
|
+
this.enqueueMessage(text);
|
|
515020
|
+
this.updateQueueDisplay();
|
|
515021
|
+
this.scheduleQueueDrain();
|
|
515022
|
+
this.state.ui.requestRender();
|
|
515023
|
+
}
|
|
515017
515024
|
beginSessionRequest() {
|
|
515018
515025
|
this.streamingUI.setTurnId(void 0);
|
|
515019
515026
|
this.streamingUI.resetLiveText();
|
package/package.json
CHANGED
|
@@ -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) => {
|