blun-king-cli 9.1.392 → 9.1.394
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 +25 -7
- package/bin/blun.js +28 -43
- package/bin/cognitive-memory-provider.cjs +92 -0
- package/bin/cognitive-turn-lifecycle.cjs +18 -3
- package/bin/core-bootstrap.js +1 -2
- package/bin/king.js +28 -43
- package/bin/launcher-runtime.js +82 -657
- package/bin/update-notice.js +22 -126
- package/blun.mjs +11 -1703
- package/package.json +1 -1
- package/release-planned-removals.json +13 -2
- package/bin/running-update-preference.cjs +0 -68
- package/bin/running-update.cjs +0 -588
package/bin/launcher-runtime.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
|
|
2
3
|
/*
|
|
3
|
-
* BLUN CLI
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* BLUN CLI launcher. It prepares the local profile and then starts the bundled
|
|
5
|
+
* core directly. Updates are offered only through the interactive startup
|
|
6
|
+
* picker; no background download or deferred activation runs here. A user-
|
|
7
|
+
* selected update may relaunch only an explicit `king -c` resume request.
|
|
6
8
|
*/
|
|
7
9
|
const fs = require('node:fs');
|
|
8
10
|
const path = require('node:path');
|
|
@@ -23,36 +25,12 @@ const {
|
|
|
23
25
|
seedStandardSkills,
|
|
24
26
|
seedStandardTools,
|
|
25
27
|
} = require('./standard-tools-bootstrap');
|
|
26
|
-
const { CORE_LOADED_MESSAGE
|
|
28
|
+
const { CORE_LOADED_MESSAGE } = require('./core-bootstrap');
|
|
27
29
|
const { prepareManagedNodeRuntime } = require('./node-runtime');
|
|
28
30
|
const { repairConfiguredNativeModules } = require('./native-module-repair');
|
|
29
31
|
const { startMnemoConnectHeartbeat } = require('./mnemo-connect-heartbeat.cjs');
|
|
30
|
-
const { acquireSharedRuntimeLease
|
|
31
|
-
const {
|
|
32
|
-
const {
|
|
33
|
-
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
34
|
-
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
35
|
-
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
36
|
-
RUNNING_UPDATE_MODE_MESSAGE,
|
|
37
|
-
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
38
|
-
RUNTIME_EXIT_INTENT_MESSAGE,
|
|
39
|
-
activateRuntime,
|
|
40
|
-
clearActiveRuntime,
|
|
41
|
-
prepareRunningUpdate,
|
|
42
|
-
pruneRunningUpdateReleases,
|
|
43
|
-
recordRunningUpdateEvent,
|
|
44
|
-
readActiveRuntime,
|
|
45
|
-
readPendingRuntime,
|
|
46
|
-
restoreActiveRuntime,
|
|
47
|
-
clearPendingRuntime,
|
|
48
|
-
handoffArgsForMode,
|
|
49
|
-
stageRuntime,
|
|
50
|
-
} = require('./running-update.cjs');
|
|
51
|
-
const {
|
|
52
|
-
RUNNING_UPDATE_MODES,
|
|
53
|
-
normalizeRunningUpdateMode,
|
|
54
|
-
readRunningUpdateMode,
|
|
55
|
-
} = require('./running-update-preference.cjs');
|
|
32
|
+
const { acquireSharedRuntimeLease } = require('./update-lease');
|
|
33
|
+
const { runExplicitUpdate, runUpdateNotice } = require('./update-notice');
|
|
56
34
|
const {
|
|
57
35
|
ensurePrivateDirectory,
|
|
58
36
|
securePrivateFile,
|
|
@@ -69,40 +47,6 @@ const RAW_ARGS = process.argv.slice(2);
|
|
|
69
47
|
const PROFILE = parseProfileLaunchArgs(RAW_ARGS, launcherModeFromArgv(process.argv));
|
|
70
48
|
const ARGS = PROFILE.args;
|
|
71
49
|
const CORE_LOAD_TIMEOUT_MS = 30_000;
|
|
72
|
-
const RUNNING_UPDATE_RESUME_SESSION_ENV = 'BLUN_RUNNING_UPDATE_RESUME_SESSION_ID';
|
|
73
|
-
const RUNTIME_READY_TIMEOUT_MS = 60_000;
|
|
74
|
-
const RUNNING_UPDATE_RECHECK_MS = 5 * 60_000;
|
|
75
|
-
const RUNNING_UPDATE_RECHECK_JITTER_MS = 2 * 60_000;
|
|
76
|
-
const RUNNING_UPDATE_ERROR_RETRY_MS = 10_000;
|
|
77
|
-
const RUNNING_UPDATE_STABILIZATION_MS = 2 * 60 * 1000;
|
|
78
|
-
|
|
79
|
-
function runningUpdateRecheckDelay(randomValue = Math.random()) {
|
|
80
|
-
const normalized = Number.isFinite(randomValue)
|
|
81
|
-
? Math.min(Math.max(randomValue, 0), 0.999999999)
|
|
82
|
-
: 0;
|
|
83
|
-
return RUNNING_UPDATE_RECHECK_MS
|
|
84
|
-
+ Math.floor(normalized * RUNNING_UPDATE_RECHECK_JITTER_MS);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function scheduleRunningUpdateRecheck(callback, options = {}) {
|
|
88
|
-
const timer = (options.setTimeoutImpl || setTimeout)(
|
|
89
|
-
callback,
|
|
90
|
-
options.delayMs ?? runningUpdateRecheckDelay((options.randomImpl || Math.random)()),
|
|
91
|
-
);
|
|
92
|
-
timer.unref?.();
|
|
93
|
-
return timer;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function runningUpdateFailureDetails(error) {
|
|
97
|
-
const safeField = (value, fallback) => typeof value === 'string'
|
|
98
|
-
&& /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u.test(value)
|
|
99
|
-
? value
|
|
100
|
-
: fallback;
|
|
101
|
-
return {
|
|
102
|
-
errorName: safeField(error?.name, 'Error'),
|
|
103
|
-
errorCode: safeField(error?.code, 'UNKNOWN'),
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
50
|
|
|
107
51
|
function normalizeWindowsPath(value) {
|
|
108
52
|
return path.win32.normalize(value).replace(/\\+$/u, '').toLowerCase();
|
|
@@ -209,10 +153,8 @@ function spawnProtectedCore(args, env, cwd, options = {}) {
|
|
|
209
153
|
},
|
|
210
154
|
);
|
|
211
155
|
let loadedSettled = false;
|
|
212
|
-
let readySettled = false;
|
|
213
156
|
let completedSettled = false;
|
|
214
157
|
let resolveLoaded;
|
|
215
|
-
let resolveReady;
|
|
216
158
|
let resolveCompleted;
|
|
217
159
|
const loadTimer = setTimeout(() => {
|
|
218
160
|
try {
|
|
@@ -220,7 +162,6 @@ function spawnProtectedCore(args, env, cwd, options = {}) {
|
|
|
220
162
|
} catch {}
|
|
221
163
|
}, CORE_LOAD_TIMEOUT_MS);
|
|
222
164
|
const loaded = new Promise((resolve) => { resolveLoaded = resolve; });
|
|
223
|
-
const ready = new Promise((resolve) => { resolveReady = resolve; });
|
|
224
165
|
const completed = new Promise((resolve) => { resolveCompleted = resolve; });
|
|
225
166
|
const settleLoaded = (value) => {
|
|
226
167
|
if (loadedSettled) return;
|
|
@@ -228,17 +169,11 @@ function spawnProtectedCore(args, env, cwd, options = {}) {
|
|
|
228
169
|
clearTimeout(loadTimer);
|
|
229
170
|
resolveLoaded(value);
|
|
230
171
|
};
|
|
231
|
-
const settleReady = (value) => {
|
|
232
|
-
if (readySettled) return;
|
|
233
|
-
readySettled = true;
|
|
234
|
-
resolveReady(value);
|
|
235
|
-
};
|
|
236
172
|
const settleCompleted = (result) => {
|
|
237
173
|
if (completedSettled) return;
|
|
238
174
|
completedSettled = true;
|
|
239
175
|
for (const [signal, handler] of signalHandlers) process.removeListener(signal, handler);
|
|
240
176
|
settleLoaded(false);
|
|
241
|
-
settleReady(false);
|
|
242
177
|
resolveCompleted(result);
|
|
243
178
|
};
|
|
244
179
|
const signalHandlers = new Map();
|
|
@@ -253,416 +188,40 @@ function spawnProtectedCore(args, env, cwd, options = {}) {
|
|
|
253
188
|
}
|
|
254
189
|
child.on('message', (message) => {
|
|
255
190
|
if (message?.type === CORE_LOADED_MESSAGE) settleLoaded(true);
|
|
256
|
-
if (message?.type === RUNTIME_READY_MESSAGE) settleReady(true);
|
|
257
191
|
options.onMessage?.(message, child);
|
|
258
192
|
});
|
|
259
193
|
child.once('error', (error) => settleCompleted({ error }));
|
|
260
194
|
child.once('exit', (code, signal) => settleCompleted({ code, signal }));
|
|
261
|
-
return { child, completed, loaded, packageRoot
|
|
195
|
+
return { child, completed, loaded, packageRoot };
|
|
262
196
|
}
|
|
263
197
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
try {
|
|
271
|
-
return await Promise.race([core.ready, timedOut]);
|
|
272
|
-
} finally {
|
|
273
|
-
clearTimeout(timer);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function resolveHandoffCwd(candidate, fallback) {
|
|
278
|
-
if (typeof candidate !== 'string' || candidate.trim().length === 0 || !path.isAbsolute(candidate)) {
|
|
279
|
-
return fallback;
|
|
280
|
-
}
|
|
281
|
-
try {
|
|
282
|
-
return fs.statSync(candidate).isDirectory() ? path.resolve(candidate) : fallback;
|
|
283
|
-
} catch {
|
|
284
|
-
return fallback;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function isAutomaticRunningUpdateMode(mode) {
|
|
289
|
-
return mode === RUNNING_UPDATE_MODES.RESUME || mode === RUNNING_UPDATE_MODES.NEW;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function shouldLaunchPreparedRuntimeAutomatically(runtime, mode) {
|
|
293
|
-
return runtime !== undefined
|
|
294
|
-
&& runtime !== null
|
|
295
|
-
&& isAutomaticRunningUpdateMode(mode)
|
|
296
|
-
&& runtime.mode === mode;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
async function prepareAutomaticStartupRuntime(options) {
|
|
300
|
-
if (options.existingRuntime !== undefined) return options.existingRuntime;
|
|
301
|
-
const runningUpdateMode = readRunningUpdateMode(options.profileHome);
|
|
302
|
-
if (!isAutomaticRunningUpdateMode(runningUpdateMode)) return undefined;
|
|
303
|
-
const target = await (options.prepareRunningUpdate || prepareRunningUpdate)({
|
|
304
|
-
currentVersion: options.currentVersion,
|
|
305
|
-
sharedHome: options.sharedHome,
|
|
306
|
-
env: options.env,
|
|
307
|
-
});
|
|
308
|
-
if (target === null) return undefined;
|
|
309
|
-
(options.stageRuntime || stageRuntime)(options.sharedHome, target, {
|
|
310
|
-
mode: runningUpdateMode,
|
|
311
|
-
cwd: options.cwd,
|
|
312
|
-
});
|
|
313
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(options.sharedHome, {
|
|
314
|
-
event: 'prepared-on-cold-start',
|
|
315
|
-
fromVersion: options.currentVersion,
|
|
316
|
-
toVersion: target.version,
|
|
317
|
-
});
|
|
318
|
-
return (options.readPendingRuntime || readPendingRuntime)(options.sharedHome)
|
|
319
|
-
|| Object.freeze({ ...target, mode: runningUpdateMode, cwd: options.cwd });
|
|
198
|
+
function exitCodeForChild(result, loaded) {
|
|
199
|
+
if (!loaded && result.code === 75) return 0;
|
|
200
|
+
if (Number.isInteger(result.code)) return result.code;
|
|
201
|
+
if (result.signal === 'SIGINT') return 130;
|
|
202
|
+
if (result.signal === 'SIGTERM') return 143;
|
|
203
|
+
return 1;
|
|
320
204
|
}
|
|
321
205
|
|
|
322
|
-
function
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return now - recovery.activatedAt <= RUNNING_UPDATE_STABILIZATION_MS;
|
|
206
|
+
function shouldResumeAfterStartupUpdate(args, updateResult) {
|
|
207
|
+
return updateResult?.kind === 'installed'
|
|
208
|
+
&& Array.isArray(args)
|
|
209
|
+
&& args.length === 1
|
|
210
|
+
&& args[0] === '-c';
|
|
328
211
|
}
|
|
329
212
|
|
|
330
|
-
async function superviseProtectedCore(args, env, cwd,
|
|
331
|
-
const packageRoot = path.resolve(options.packageRoot || PKG);
|
|
332
|
-
let preparedTarget;
|
|
333
|
-
let updateStarted = false;
|
|
334
|
-
let runtimeReady = options.initialRuntimeReady === true;
|
|
335
|
-
let activeSession = options.initialActiveSession;
|
|
336
|
-
let acceptedHandoff;
|
|
337
|
-
let runtimeExitIntent = false;
|
|
338
|
-
let supervisionCompleted = false;
|
|
339
|
-
let runningUpdatePollTimer;
|
|
340
|
-
let runningUpdateMode = readRunningUpdateMode(env.BLUN_HOME);
|
|
341
|
-
const automaticMode = () => runningUpdateMode === RUNNING_UPDATE_MODES.RESUME
|
|
342
|
-
|| runningUpdateMode === RUNNING_UPDATE_MODES.NEW;
|
|
343
|
-
const refreshRunningUpdateMode = () => {
|
|
344
|
-
const persistedMode = readRunningUpdateMode(env.BLUN_HOME);
|
|
345
|
-
if (persistedMode !== runningUpdateMode) {
|
|
346
|
-
runningUpdateMode = persistedMode;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
const clearRunningUpdatePoll = () => {
|
|
350
|
-
if (runningUpdatePollTimer === undefined) return;
|
|
351
|
-
(options.clearTimeoutImpl || clearTimeout)(runningUpdatePollTimer);
|
|
352
|
-
runningUpdatePollTimer = undefined;
|
|
353
|
-
};
|
|
354
|
-
const validSessionMessage = (message) => typeof message?.sessionId === 'string'
|
|
355
|
-
&& message.sessionId.length > 0
|
|
356
|
-
&& message.sessionId.length <= 256
|
|
357
|
-
&& !/[\u0000-\u001f\u007f]/u.test(message.sessionId)
|
|
358
|
-
&& resolveHandoffCwd(message.cwd, '') !== '';
|
|
359
|
-
const stagedRuntimeOptions = () => ({
|
|
360
|
-
mode: runningUpdateMode,
|
|
361
|
-
...(runningUpdateMode === RUNNING_UPDATE_MODES.RESUME && activeSession !== undefined
|
|
362
|
-
? { cwd: activeSession.cwd, sessionId: activeSession.sessionId }
|
|
363
|
-
: {}),
|
|
364
|
-
});
|
|
365
|
-
const persistPreparedRuntime = () => {
|
|
366
|
-
if (preparedTarget === undefined) return;
|
|
367
|
-
const sharedHome = env.BLUN_SHARED_HOME;
|
|
368
|
-
if (typeof sharedHome !== 'string' || sharedHome.length === 0) return;
|
|
369
|
-
(options.stageRuntime || stageRuntime)(sharedHome, preparedTarget, stagedRuntimeOptions());
|
|
370
|
-
};
|
|
371
|
-
const scheduleNextPreparation = (child, scheduleOptions = {}) => {
|
|
372
|
-
clearRunningUpdatePoll();
|
|
373
|
-
if (supervisionCompleted || updateStarted) return;
|
|
374
|
-
runningUpdatePollTimer = (options.scheduleRunningUpdateRecheck || scheduleRunningUpdateRecheck)(() => {
|
|
375
|
-
runningUpdatePollTimer = undefined;
|
|
376
|
-
refreshRunningUpdateMode();
|
|
377
|
-
if (automaticMode()) startPreparation(child);
|
|
378
|
-
else scheduleNextPreparation(child);
|
|
379
|
-
}, scheduleOptions);
|
|
380
|
-
};
|
|
381
|
-
const startPreparation = (child) => {
|
|
382
|
-
if (supervisionCompleted || updateStarted
|
|
383
|
-
|| options.runningUpdate === false || !automaticMode()) return;
|
|
384
|
-
updateStarted = true;
|
|
385
|
-
const sharedHome = env.BLUN_SHARED_HOME;
|
|
386
|
-
if (typeof sharedHome !== 'string' || sharedHome.length === 0) {
|
|
387
|
-
updateStarted = false;
|
|
388
|
-
scheduleNextPreparation(child);
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
Promise.resolve((options.prepareRunningUpdate || prepareRunningUpdate)({
|
|
392
|
-
currentVersion: JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')).version,
|
|
393
|
-
sharedHome,
|
|
394
|
-
env,
|
|
395
|
-
})).then((target) => {
|
|
396
|
-
if (target === null) {
|
|
397
|
-
updateStarted = false;
|
|
398
|
-
scheduleNextPreparation(child);
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
const previousTarget = preparedTarget;
|
|
402
|
-
if (previousTarget !== undefined
|
|
403
|
-
&& compareSemver(target.version, previousTarget.version) !== 1) {
|
|
404
|
-
updateStarted = false;
|
|
405
|
-
scheduleNextPreparation(child);
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
preparedTarget = target;
|
|
409
|
-
persistPreparedRuntime();
|
|
410
|
-
if (child?.connected === true) {
|
|
411
|
-
try {
|
|
412
|
-
child.send({
|
|
413
|
-
type: RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
414
|
-
version: target.version,
|
|
415
|
-
mode: runningUpdateMode,
|
|
416
|
-
});
|
|
417
|
-
} catch {}
|
|
418
|
-
}
|
|
419
|
-
const runningVersion = readPackageVersionAt(packageRoot);
|
|
420
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(sharedHome, previousTarget === undefined ? {
|
|
421
|
-
event: 'prepared-for-next-start',
|
|
422
|
-
fromVersion: runningVersion,
|
|
423
|
-
toVersion: target.version,
|
|
424
|
-
} : {
|
|
425
|
-
event: 'prepared-target-refreshed',
|
|
426
|
-
fromVersion: previousTarget.version,
|
|
427
|
-
toVersion: target.version,
|
|
428
|
-
runningVersion,
|
|
429
|
-
}, { now: options.nowImpl });
|
|
430
|
-
Promise.resolve((options.pruneRunningUpdateReleases || pruneRunningUpdateReleases)(sharedHome, {
|
|
431
|
-
activePackageRoot: packageRoot,
|
|
432
|
-
})).catch((error) => options.onRunningUpdateError?.(error));
|
|
433
|
-
updateStarted = false;
|
|
434
|
-
scheduleNextPreparation(child);
|
|
435
|
-
}).catch((error) => {
|
|
436
|
-
updateStarted = false;
|
|
437
|
-
options.onRunningUpdateError?.(error);
|
|
438
|
-
try {
|
|
439
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(sharedHome, {
|
|
440
|
-
event: 'prepare-failed',
|
|
441
|
-
runningVersion: readPackageVersionAt(packageRoot),
|
|
442
|
-
...runningUpdateFailureDetails(error),
|
|
443
|
-
}, { now: options.nowImpl });
|
|
444
|
-
} catch (recordError) {
|
|
445
|
-
options.onRunningUpdateError?.(recordError);
|
|
446
|
-
}
|
|
447
|
-
scheduleNextPreparation(child, { delayMs: RUNNING_UPDATE_ERROR_RETRY_MS });
|
|
448
|
-
});
|
|
449
|
-
};
|
|
450
|
-
const handleCoreMessage = (message, child) => {
|
|
451
|
-
if (message?.type === RUNTIME_EXIT_INTENT_MESSAGE) runtimeExitIntent = true;
|
|
452
|
-
if (message?.type === RUNTIME_READY_MESSAGE) {
|
|
453
|
-
if (validSessionMessage(message)) {
|
|
454
|
-
activeSession = Object.freeze({
|
|
455
|
-
cwd: resolveHandoffCwd(message.cwd, cwd),
|
|
456
|
-
sessionId: message.sessionId,
|
|
457
|
-
});
|
|
458
|
-
try {
|
|
459
|
-
persistPreparedRuntime();
|
|
460
|
-
} catch (error) {
|
|
461
|
-
options.onRunningUpdateError?.(error);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
runtimeReady = true;
|
|
465
|
-
refreshRunningUpdateMode();
|
|
466
|
-
if (automaticMode()) startPreparation(child);
|
|
467
|
-
else scheduleNextPreparation(child);
|
|
468
|
-
}
|
|
469
|
-
if (message?.type === RUNNING_UPDATE_MODE_MESSAGE && typeof message.mode === 'string') {
|
|
470
|
-
runningUpdateMode = normalizeRunningUpdateMode(message.mode);
|
|
471
|
-
clearRunningUpdatePoll();
|
|
472
|
-
if (automaticMode()) {
|
|
473
|
-
if (runtimeReady && !updateStarted) startPreparation(child);
|
|
474
|
-
} else if (runtimeReady) scheduleNextPreparation(child);
|
|
475
|
-
}
|
|
476
|
-
if (message?.type === RUNNING_UPDATE_HANDOFF_MESSAGE) {
|
|
477
|
-
refreshRunningUpdateMode();
|
|
478
|
-
const requestedCwd = resolveHandoffCwd(message.cwd, '');
|
|
479
|
-
const requestMatches = preparedTarget !== undefined
|
|
480
|
-
&& automaticMode()
|
|
481
|
-
&& validSessionMessage(message)
|
|
482
|
-
&& activeSession !== undefined
|
|
483
|
-
&& message.version === preparedTarget.version
|
|
484
|
-
&& message.mode === runningUpdateMode
|
|
485
|
-
&& message.sessionId === activeSession.sessionId
|
|
486
|
-
&& requestedCwd === activeSession.cwd;
|
|
487
|
-
if (!requestMatches) return;
|
|
488
|
-
acceptedHandoff = Object.freeze({
|
|
489
|
-
cwd: requestedCwd,
|
|
490
|
-
mode: runningUpdateMode,
|
|
491
|
-
sessionId: message.sessionId,
|
|
492
|
-
target: preparedTarget,
|
|
493
|
-
});
|
|
494
|
-
if (child?.connected === true) {
|
|
495
|
-
try {
|
|
496
|
-
child.send({
|
|
497
|
-
type: RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
498
|
-
version: preparedTarget.version,
|
|
499
|
-
mode: runningUpdateMode,
|
|
500
|
-
sessionId: message.sessionId,
|
|
501
|
-
});
|
|
502
|
-
} catch {}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
};
|
|
213
|
+
async function superviseProtectedCore(args, env, cwd, releaseLauncherLeases, options = {}) {
|
|
506
214
|
const spawnCore = options.spawnProtectedCore || spawnProtectedCore;
|
|
507
215
|
const core = options.existingCore || spawnCore(args, env, cwd, {
|
|
508
|
-
packageRoot,
|
|
509
|
-
onMessage: handleCoreMessage,
|
|
216
|
+
packageRoot: options.packageRoot || PKG,
|
|
510
217
|
});
|
|
511
|
-
let existingMessageHandler;
|
|
512
|
-
if (options.existingCore) {
|
|
513
|
-
existingMessageHandler = (message) => handleCoreMessage(message, core.child);
|
|
514
|
-
core.child.on('message', existingMessageHandler);
|
|
515
|
-
}
|
|
516
218
|
const loaded = await core.loaded;
|
|
517
|
-
if (loaded
|
|
518
|
-
await (options.activateRuntime || activateRuntime)(env.BLUN_SHARED_HOME, options.startupPendingRuntime);
|
|
519
|
-
(options.clearPendingRuntime || clearPendingRuntime)(env.BLUN_SHARED_HOME, options.startupPendingRuntime);
|
|
520
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(env.BLUN_SHARED_HOME, {
|
|
521
|
-
event: 'activated-on-start',
|
|
522
|
-
version: options.startupPendingRuntime.version,
|
|
523
|
-
}, { now: options.nowImpl });
|
|
524
|
-
} else if (loaded && options.staleActiveRuntime !== undefined) {
|
|
525
|
-
(options.clearActiveRuntime || clearActiveRuntime)(env.BLUN_SHARED_HOME, options.staleActiveRuntime);
|
|
526
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(env.BLUN_SHARED_HOME, {
|
|
527
|
-
event: 'stale-active-cleared',
|
|
528
|
-
staleVersion: options.staleActiveRuntime.version,
|
|
529
|
-
runningVersion: readPackageVersionAt(packageRoot),
|
|
530
|
-
}, { now: options.nowImpl });
|
|
531
|
-
}
|
|
532
|
-
if (loaded && !runtimeReady) {
|
|
533
|
-
// Core load is an independent readiness signal. Start the download even
|
|
534
|
-
// when the later TUI-ready IPC message is lost; handoff still waits for
|
|
535
|
-
// the TUI's fully idle boundary.
|
|
536
|
-
runtimeReady = true;
|
|
537
|
-
refreshRunningUpdateMode();
|
|
538
|
-
if (automaticMode()) startPreparation(core.child);
|
|
539
|
-
else scheduleNextPreparation(core.child);
|
|
540
|
-
}
|
|
541
|
-
await releaseNotice();
|
|
219
|
+
if (loaded) await releaseLauncherLeases();
|
|
542
220
|
const result = await core.completed;
|
|
543
|
-
supervisionCompleted = true;
|
|
544
|
-
clearRunningUpdatePoll();
|
|
545
|
-
if (existingMessageHandler) core.child.off('message', existingMessageHandler);
|
|
546
|
-
if (result.code === RUNNING_UPDATE_HANDOFF_EXIT_CODE && acceptedHandoff !== undefined) {
|
|
547
|
-
const sharedHome = env.BLUN_SHARED_HOME;
|
|
548
|
-
const previousActiveRuntime = (options.readActiveRuntime || readActiveRuntime)(sharedHome);
|
|
549
|
-
const previousVersion = readPackageVersionAt(packageRoot);
|
|
550
|
-
const handoffArgs = handoffArgsForMode(args, acceptedHandoff.mode, acceptedHandoff.sessionId);
|
|
551
|
-
let targetSession;
|
|
552
|
-
const targetCore = spawnCore(handoffArgs, env, acceptedHandoff.cwd, {
|
|
553
|
-
packageRoot: acceptedHandoff.target.packageRoot,
|
|
554
|
-
onMessage(message) {
|
|
555
|
-
if (message?.type === RUNTIME_READY_MESSAGE && validSessionMessage(message)) {
|
|
556
|
-
targetSession = Object.freeze({
|
|
557
|
-
cwd: resolveHandoffCwd(message.cwd, acceptedHandoff.cwd),
|
|
558
|
-
sessionId: message.sessionId,
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
},
|
|
562
|
-
});
|
|
563
|
-
const targetLoaded = await targetCore.loaded;
|
|
564
|
-
const targetReady = targetLoaded
|
|
565
|
-
&& await (options.waitForRuntimeReady || waitForRuntimeReady)(targetCore, options.readyTimeoutMs);
|
|
566
|
-
if (targetReady) {
|
|
567
|
-
await (options.activateRuntime || activateRuntime)(sharedHome, acceptedHandoff.target);
|
|
568
|
-
(options.clearPendingRuntime || clearPendingRuntime)(sharedHome, acceptedHandoff.target);
|
|
569
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(sharedHome, {
|
|
570
|
-
event: 'activated-live-handoff',
|
|
571
|
-
fromVersion: previousVersion,
|
|
572
|
-
toVersion: acceptedHandoff.target.version,
|
|
573
|
-
mode: acceptedHandoff.mode,
|
|
574
|
-
sessionId: acceptedHandoff.sessionId,
|
|
575
|
-
}, { now: options.nowImpl });
|
|
576
|
-
return superviseProtectedCore(handoffArgs, env, acceptedHandoff.cwd, async () => {}, {
|
|
577
|
-
...options,
|
|
578
|
-
existingCore: targetCore,
|
|
579
|
-
initialActiveSession: targetSession,
|
|
580
|
-
initialRuntimeReady: true,
|
|
581
|
-
packageRoot: acceptedHandoff.target.packageRoot,
|
|
582
|
-
startupPendingRuntime: undefined,
|
|
583
|
-
staleActiveRuntime: undefined,
|
|
584
|
-
recoveryRuntime: {
|
|
585
|
-
activeRuntime: previousActiveRuntime,
|
|
586
|
-
activatedAt: (options.nowImpl || Date.now)(),
|
|
587
|
-
packageRoot,
|
|
588
|
-
version: previousVersion,
|
|
589
|
-
},
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
try {
|
|
593
|
-
targetCore.child.kill();
|
|
594
|
-
} catch {}
|
|
595
|
-
await (options.restoreActiveRuntime || restoreActiveRuntime)(sharedHome, previousActiveRuntime);
|
|
596
|
-
(options.clearPendingRuntime || clearPendingRuntime)(sharedHome, acceptedHandoff.target);
|
|
597
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(sharedHome, {
|
|
598
|
-
event: 'live-handoff-rolled-back',
|
|
599
|
-
failedVersion: acceptedHandoff.target.version,
|
|
600
|
-
recoveryVersion: previousVersion,
|
|
601
|
-
}, { now: options.nowImpl });
|
|
602
|
-
const fallback = spawnCore(handoffArgs, env, acceptedHandoff.cwd, { packageRoot });
|
|
603
|
-
const fallbackLoaded = await fallback.loaded;
|
|
604
|
-
const fallbackReady = fallbackLoaded
|
|
605
|
-
&& await (options.waitForRuntimeReady || waitForRuntimeReady)(fallback, options.readyTimeoutMs);
|
|
606
|
-
if (fallbackReady) {
|
|
607
|
-
return superviseProtectedCore(handoffArgs, env, acceptedHandoff.cwd, async () => {}, {
|
|
608
|
-
...options,
|
|
609
|
-
existingCore: fallback,
|
|
610
|
-
initialActiveSession: activeSession,
|
|
611
|
-
initialRuntimeReady: true,
|
|
612
|
-
packageRoot,
|
|
613
|
-
startupPendingRuntime: undefined,
|
|
614
|
-
staleActiveRuntime: undefined,
|
|
615
|
-
recoveryRuntime: undefined,
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
const fallbackResult = await fallback.completed;
|
|
619
|
-
if (fallbackResult.error) throw fallbackResult.error;
|
|
620
|
-
return exitCodeForChild(fallbackResult, fallbackLoaded);
|
|
621
|
-
}
|
|
622
|
-
const recovery = options.recoveryRuntime;
|
|
623
|
-
if (shouldRecoverActivatedRuntime(result, recovery, {
|
|
624
|
-
now: (options.nowImpl || Date.now)(),
|
|
625
|
-
runtimeExitIntent,
|
|
626
|
-
})) {
|
|
627
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(env.BLUN_SHARED_HOME, {
|
|
628
|
-
event: 'post-activation-exit',
|
|
629
|
-
activeVersion: readPackageVersionAt(packageRoot),
|
|
630
|
-
code: Number.isInteger(result.code) ? result.code : null,
|
|
631
|
-
error: result.error?.message || null,
|
|
632
|
-
signal: result.signal || null,
|
|
633
|
-
recoveryVersion: recovery.version,
|
|
634
|
-
}, { now: options.nowImpl });
|
|
635
|
-
await (options.restoreActiveRuntime || restoreActiveRuntime)(env.BLUN_SHARED_HOME, recovery.activeRuntime);
|
|
636
|
-
const fallback = spawnCore(args, env, cwd, { packageRoot: recovery.packageRoot });
|
|
637
|
-
const fallbackLoaded = await fallback.loaded;
|
|
638
|
-
const fallbackReady = fallbackLoaded && await waitForRuntimeReady(fallback, options.readyTimeoutMs);
|
|
639
|
-
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(env.BLUN_SHARED_HOME, {
|
|
640
|
-
event: fallbackReady ? 'recovery-ready' : 'recovery-failed',
|
|
641
|
-
version: recovery.version,
|
|
642
|
-
}, { now: options.nowImpl });
|
|
643
|
-
if (fallbackReady) {
|
|
644
|
-
return superviseProtectedCore(args, env, cwd, async () => {}, {
|
|
645
|
-
...options,
|
|
646
|
-
existingCore: fallback,
|
|
647
|
-
packageRoot: recovery.packageRoot,
|
|
648
|
-
startupPendingRuntime: undefined,
|
|
649
|
-
staleActiveRuntime: undefined,
|
|
650
|
-
recoveryRuntime: undefined,
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
221
|
if (result.error) throw result.error;
|
|
655
222
|
return exitCodeForChild(result, loaded);
|
|
656
223
|
}
|
|
657
224
|
|
|
658
|
-
function exitCodeForChild(result, loaded) {
|
|
659
|
-
if (!loaded && result.code === 75) return 0;
|
|
660
|
-
if (Number.isInteger(result.code)) return result.code;
|
|
661
|
-
if (result.signal === 'SIGINT') return 130;
|
|
662
|
-
if (result.signal === 'SIGTERM') return 143;
|
|
663
|
-
return 1;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
225
|
function installTelegramForProfile(packageRoot, blunDir) {
|
|
667
226
|
installManagedTelegramPlugin({ packageRoot, blunDir });
|
|
668
227
|
const channelsDir = path.join(blunDir, 'channels');
|
|
@@ -725,101 +284,22 @@ function spawnManagedLauncher(binary, cwd) {
|
|
|
725
284
|
});
|
|
726
285
|
}
|
|
727
286
|
|
|
728
|
-
function spawnActiveLauncher(packageRoot, cwd, args = RAW_ARGS, options = {}) {
|
|
729
|
-
const entryName = path.basename(process.argv[1] || 'king.js').toLowerCase() === 'blun.js'
|
|
730
|
-
? 'blun.js'
|
|
731
|
-
: 'king.js';
|
|
732
|
-
return new Promise((resolve, reject) => {
|
|
733
|
-
const child = spawn(process.execPath, [path.join(packageRoot, 'bin', entryName), ...args], {
|
|
734
|
-
cwd,
|
|
735
|
-
env: {
|
|
736
|
-
...process.env,
|
|
737
|
-
BLUN_ACTIVE_RUNTIME_ROOT: packageRoot,
|
|
738
|
-
...(typeof options.resumeSessionId === 'string' && options.resumeSessionId.length > 0
|
|
739
|
-
? { [RUNNING_UPDATE_RESUME_SESSION_ENV]: options.resumeSessionId }
|
|
740
|
-
: {}),
|
|
741
|
-
},
|
|
742
|
-
stdio: 'inherit',
|
|
743
|
-
windowsHide: true,
|
|
744
|
-
});
|
|
745
|
-
child.once('error', reject);
|
|
746
|
-
child.once('exit', (code, signal) => {
|
|
747
|
-
if (Number.isInteger(code)) resolve(code);
|
|
748
|
-
else if (signal === 'SIGINT') resolve(130);
|
|
749
|
-
else if (signal === 'SIGTERM') resolve(143);
|
|
750
|
-
else resolve(1);
|
|
751
|
-
});
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
|
|
755
287
|
async function runLauncher(options = {}) {
|
|
756
288
|
const callerCwd = process.cwd();
|
|
757
|
-
let startupPendingRuntime;
|
|
758
|
-
let deferredPendingRuntime;
|
|
759
|
-
let staleActiveRuntime;
|
|
760
|
-
if (options.skipActiveRuntime !== true) {
|
|
761
|
-
const activeHome = resolveLauncherPrivatePaths().sharedHome;
|
|
762
|
-
const pendingRuntime = readPendingRuntime(activeHome);
|
|
763
|
-
const activeRuntime = readActiveRuntime(activeHome);
|
|
764
|
-
const currentVersion = readPackageVersion();
|
|
765
|
-
if (pendingRuntime !== null
|
|
766
|
-
&& path.resolve(pendingRuntime.packageRoot) !== PKG
|
|
767
|
-
&& compareSemver(currentVersion, pendingRuntime.version) === -1) {
|
|
768
|
-
deferredPendingRuntime = pendingRuntime;
|
|
769
|
-
}
|
|
770
|
-
if (pendingRuntime !== null && path.resolve(pendingRuntime.packageRoot) === PKG) {
|
|
771
|
-
startupPendingRuntime = pendingRuntime;
|
|
772
|
-
}
|
|
773
|
-
if (startupPendingRuntime === undefined && deferredPendingRuntime === undefined && activeRuntime !== null
|
|
774
|
-
&& path.resolve(activeRuntime.packageRoot) !== PKG
|
|
775
|
-
&& compareSemver(currentVersion, activeRuntime.version) === -1) {
|
|
776
|
-
process.exitCode = await spawnActiveLauncher(activeRuntime.packageRoot, callerCwd);
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
if (activeRuntime !== null
|
|
780
|
-
&& path.resolve(activeRuntime.packageRoot) !== PKG
|
|
781
|
-
&& compareSemver(currentVersion, activeRuntime.version) >= 0) {
|
|
782
|
-
staleActiveRuntime = activeRuntime;
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
289
|
const mode = options.mode || launcherModeFromArgv(process.argv);
|
|
786
290
|
const explicitUpdateRequest = isNpmPackageUpdateRequest(ARGS);
|
|
787
291
|
const explicitToolsRequest = String(ARGS[0] || '').toLowerCase() === 'tools';
|
|
788
|
-
const
|
|
789
|
-
? { acquired: true, lease: { assertOwned() {}, async release() {} } }
|
|
790
|
-
: options.noticeLease
|
|
791
|
-
? { acquired: true, lease: options.noticeLease }
|
|
792
|
-
: await tryAcquireUpdateLease({ packageRoot: PKG, role: 'notice' });
|
|
793
|
-
if (!noticeResult.acquired) {
|
|
794
|
-
if (explicitUpdateRequest) {
|
|
795
|
-
process.stderr.write('Das Update konnte nicht verifiziert werden.\n');
|
|
796
|
-
process.exitCode = 1;
|
|
797
|
-
}
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
const noticeLease = noticeResult.lease;
|
|
292
|
+
const launcherLease = options.noticeLease;
|
|
801
293
|
let runtimeLease = options.runtimeLease;
|
|
802
|
-
let
|
|
803
|
-
const
|
|
804
|
-
if (
|
|
805
|
-
|
|
806
|
-
await
|
|
294
|
+
let leasesReleased = false;
|
|
295
|
+
const releaseLauncherLeases = async () => {
|
|
296
|
+
if (leasesReleased) return;
|
|
297
|
+
leasesReleased = true;
|
|
298
|
+
await launcherLease?.release();
|
|
807
299
|
await runtimeLease?.release();
|
|
808
300
|
};
|
|
809
301
|
|
|
810
302
|
try {
|
|
811
|
-
if (!runtimeLease && !explicitUpdateRequest) {
|
|
812
|
-
const installProbe = await tryAcquireUpdateLease({ packageRoot: PKG, role: 'install' });
|
|
813
|
-
if (!installProbe.acquired) {
|
|
814
|
-
process.stderr.write(explicitUpdateRequest
|
|
815
|
-
? 'Das Update konnte nicht verifiziert werden.\n'
|
|
816
|
-
: 'Der geschuetzte BLUN-Start ist gerade nicht verfuegbar.\n');
|
|
817
|
-
process.exitCode = 1;
|
|
818
|
-
return;
|
|
819
|
-
}
|
|
820
|
-
await installProbe.lease.release();
|
|
821
|
-
}
|
|
822
|
-
|
|
823
303
|
if (explicitToolsRequest) {
|
|
824
304
|
const action = String(ARGS[1] || '').toLowerCase();
|
|
825
305
|
const available = availableStandardToolNames({ packageRoot: PKG });
|
|
@@ -855,28 +335,12 @@ async function runLauncher(options = {}) {
|
|
|
855
335
|
process.exitCode = 1;
|
|
856
336
|
return;
|
|
857
337
|
}
|
|
338
|
+
|
|
858
339
|
if (ARGS.some((arg) => arg === '--version' || arg === '-V')) {
|
|
859
340
|
process.stdout.write(`${readPackageVersion()}\n`);
|
|
860
341
|
return;
|
|
861
342
|
}
|
|
862
343
|
|
|
863
|
-
if (explicitUpdateRequest) {
|
|
864
|
-
const privatePaths = resolveLauncherPrivatePaths();
|
|
865
|
-
const result = await runExplicitUpdate({
|
|
866
|
-
currentVersion: readPackageVersion(),
|
|
867
|
-
env: process.env,
|
|
868
|
-
stdin: process.stdin,
|
|
869
|
-
stdout: process.stdout,
|
|
870
|
-
stderr: process.stderr,
|
|
871
|
-
blunDir: privatePaths.sharedHome,
|
|
872
|
-
packageRoot: PKG,
|
|
873
|
-
noticeLease,
|
|
874
|
-
request: ARGS[0],
|
|
875
|
-
});
|
|
876
|
-
if (result.kind === 'failed') process.exitCode = result.exitCode || 1;
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
344
|
let privatePathsCache;
|
|
881
345
|
const getPrivatePaths = () => {
|
|
882
346
|
privatePathsCache ||= resolveLauncherPrivatePaths();
|
|
@@ -892,11 +356,28 @@ async function runLauncher(options = {}) {
|
|
|
892
356
|
}
|
|
893
357
|
if (nodeRuntime.kind === 'managed') {
|
|
894
358
|
process.stdout.write('BLUN hat die passende Node.js-Laufzeit eingerichtet.\n');
|
|
895
|
-
await
|
|
359
|
+
await releaseLauncherLeases();
|
|
896
360
|
process.exitCode = await spawnManagedLauncher(nodeRuntime.binary, callerCwd);
|
|
897
361
|
return;
|
|
898
362
|
}
|
|
899
363
|
|
|
364
|
+
if (explicitUpdateRequest) {
|
|
365
|
+
const privatePaths = getPrivatePaths();
|
|
366
|
+
ensurePrivateDirectory(privatePaths.sharedHome);
|
|
367
|
+
const result = await runExplicitUpdate({
|
|
368
|
+
currentVersion: readPackageVersion(),
|
|
369
|
+
env: process.env,
|
|
370
|
+
stdin: process.stdin,
|
|
371
|
+
stdout: process.stdout,
|
|
372
|
+
stderr: process.stderr,
|
|
373
|
+
blunDir: privatePaths.sharedHome,
|
|
374
|
+
packageRoot: PKG,
|
|
375
|
+
noticeLease: launcherLease,
|
|
376
|
+
});
|
|
377
|
+
if (result.kind === 'failed') process.exitCode = result.exitCode || 1;
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
900
381
|
if (ARGS.some((arg) => arg === '--help' || arg === '-h')) {
|
|
901
382
|
process.stdout.write(launcherHelpText());
|
|
902
383
|
const env = createLauncherEnvironment(process.env, mode, readPackageVersion());
|
|
@@ -904,12 +385,25 @@ async function runLauncher(options = {}) {
|
|
|
904
385
|
delete informationalEnv.BLUN_HOME;
|
|
905
386
|
delete informationalEnv.BLUN_SHARED_HOME;
|
|
906
387
|
const privatePaths = resolveLauncherPrivatePaths({ env: informationalEnv });
|
|
907
|
-
|
|
908
|
-
env.BLUN_HOME = profilePaths.home;
|
|
388
|
+
env.BLUN_HOME = privatePaths.profilePaths.home;
|
|
909
389
|
env.BLUN_SHARED_HOME = privatePaths.sharedHome;
|
|
910
390
|
env.BLUN_LOG_HOME = privatePaths.sharedHome;
|
|
911
391
|
env.BLUN_PROFILE = PROFILE.profileName;
|
|
912
|
-
|
|
392
|
+
if (!runtimeLease) {
|
|
393
|
+
const runtimeResult = await acquireSharedRuntimeLease({ packageRoot: PKG });
|
|
394
|
+
if (!runtimeResult.acquired) {
|
|
395
|
+
process.stderr.write('Der geschuetzte BLUN-Start ist gerade nicht verfuegbar.\n');
|
|
396
|
+
process.exitCode = 1;
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
runtimeLease = runtimeResult.lease;
|
|
400
|
+
}
|
|
401
|
+
process.exitCode = await superviseProtectedCore(
|
|
402
|
+
ARGS,
|
|
403
|
+
env,
|
|
404
|
+
callerCwd,
|
|
405
|
+
releaseLauncherLeases,
|
|
406
|
+
);
|
|
913
407
|
return;
|
|
914
408
|
}
|
|
915
409
|
|
|
@@ -922,68 +416,20 @@ async function runLauncher(options = {}) {
|
|
|
922
416
|
const blunDir = profilePaths.home;
|
|
923
417
|
ensurePrivateDirectory(blunDir);
|
|
924
418
|
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
const pendingArgs = deferredPendingRuntime.mode === RUNNING_UPDATE_MODES.RESUME
|
|
940
|
-
&& deferredPendingRuntime.sessionId !== undefined
|
|
941
|
-
? handoffArgsForMode(RAW_ARGS, deferredPendingRuntime.mode, deferredPendingRuntime.sessionId)
|
|
942
|
-
: RAW_ARGS;
|
|
943
|
-
await releaseNotice();
|
|
944
|
-
process.exitCode = await spawnActiveLauncher(
|
|
945
|
-
deferredPendingRuntime.packageRoot,
|
|
946
|
-
deferredPendingRuntime.cwd || callerCwd,
|
|
947
|
-
pendingArgs,
|
|
948
|
-
deferredPendingRuntime.mode === RUNNING_UPDATE_MODES.RESUME
|
|
949
|
-
? { resumeSessionId: deferredPendingRuntime.sessionId }
|
|
950
|
-
: {},
|
|
951
|
-
);
|
|
952
|
-
return;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
// --- 1. Oeffentlicher npm-Update-Dialog. -------------------------------
|
|
956
|
-
const updateResult = options.skipUpdateNotice === true
|
|
957
|
-
? { kind: 'continue', reason: 'notice_busy' }
|
|
958
|
-
: await runUpdateNotice({
|
|
959
|
-
currentVersion: readPackageVersion(),
|
|
960
|
-
argv: ARGS,
|
|
961
|
-
env: process.env,
|
|
962
|
-
stdin: process.stdin,
|
|
963
|
-
stdout: process.stdout,
|
|
964
|
-
stderr: process.stderr,
|
|
965
|
-
blunDir: privatePaths.sharedHome,
|
|
966
|
-
packageRoot: PKG,
|
|
967
|
-
preparedRuntime: deferredPendingRuntime,
|
|
968
|
-
autoInstallPreparedRuntime: isAutomaticRunningUpdateMode(runningUpdateMode),
|
|
969
|
-
noticeLease,
|
|
970
|
-
});
|
|
971
|
-
if (updateResult.kind === 'installed'
|
|
972
|
-
&& updateResult.source === 'prepared_runtime'
|
|
973
|
-
&& deferredPendingRuntime !== undefined) {
|
|
974
|
-
const pendingArgs = deferredPendingRuntime.mode !== undefined
|
|
975
|
-
&& deferredPendingRuntime.sessionId !== undefined
|
|
976
|
-
? handoffArgsForMode(RAW_ARGS, deferredPendingRuntime.mode, deferredPendingRuntime.sessionId)
|
|
977
|
-
: RAW_ARGS;
|
|
978
|
-
await releaseNotice();
|
|
979
|
-
process.exitCode = await spawnActiveLauncher(
|
|
980
|
-
deferredPendingRuntime.packageRoot,
|
|
981
|
-
deferredPendingRuntime.cwd || callerCwd,
|
|
982
|
-
pendingArgs,
|
|
983
|
-
deferredPendingRuntime.mode === RUNNING_UPDATE_MODES.RESUME
|
|
984
|
-
? { resumeSessionId: deferredPendingRuntime.sessionId }
|
|
985
|
-
: {},
|
|
986
|
-
);
|
|
419
|
+
const updateResult = await runUpdateNotice({
|
|
420
|
+
currentVersion: readPackageVersion(),
|
|
421
|
+
argv: ARGS,
|
|
422
|
+
env: process.env,
|
|
423
|
+
stdin: process.stdin,
|
|
424
|
+
stdout: process.stdout,
|
|
425
|
+
stderr: process.stderr,
|
|
426
|
+
blunDir: privatePaths.sharedHome,
|
|
427
|
+
packageRoot: PKG,
|
|
428
|
+
noticeLease: launcherLease,
|
|
429
|
+
});
|
|
430
|
+
if (shouldResumeAfterStartupUpdate(ARGS, updateResult)) {
|
|
431
|
+
await releaseLauncherLeases();
|
|
432
|
+
process.exitCode = await spawnManagedLauncher(process.execPath, callerCwd);
|
|
987
433
|
return;
|
|
988
434
|
}
|
|
989
435
|
if (updateResult.kind === 'installed' || updateResult.kind === 'update_in_progress') return;
|
|
@@ -998,13 +444,9 @@ async function runLauncher(options = {}) {
|
|
|
998
444
|
runtimeLease = runtimeResult.lease;
|
|
999
445
|
}
|
|
1000
446
|
|
|
1001
|
-
// --- 2. Bestehende Konfiguration absichern -------------------------------
|
|
1002
|
-
// Ein frischer Start bleibt absichtlich ohne statischen Anbieter. /login
|
|
1003
|
-
// provisioniert King ueber den BLUN-OAuth-Server.
|
|
1004
447
|
const cfgFile = path.join(blunDir, 'config.toml');
|
|
1005
448
|
if (fs.existsSync(cfgFile)) securePrivateFile(cfgFile);
|
|
1006
449
|
|
|
1007
|
-
// --- 3. BLUN-Standard-MCPs additiv im Benutzerprofil einrichten ---------
|
|
1008
450
|
const standardMcpNames = availableStandardToolNames({ packageRoot: PKG })
|
|
1009
451
|
.filter((name) => name !== 'telegram');
|
|
1010
452
|
seedStandardTools({
|
|
@@ -1013,14 +455,8 @@ async function runLauncher(options = {}) {
|
|
|
1013
455
|
names: standardMcpNames,
|
|
1014
456
|
});
|
|
1015
457
|
seedConfiguredMnemoMcp({ blunDir, env: process.env });
|
|
1016
|
-
|
|
1017
|
-
// --- 4. Eigenes BLUN-Grunddesign als einzigen Standard-Skill installieren
|
|
1018
458
|
seedStandardSkills({ packageRoot: PKG, blunDir: privatePaths.sharedHome });
|
|
1019
|
-
|
|
1020
|
-
// --- 5. Telegram-Plugin + Token-Vorlage (nur King) -----------------------
|
|
1021
|
-
if (mode === LAUNCHER_MODES.KING) {
|
|
1022
|
-
installTelegramForProfile(PKG, blunDir);
|
|
1023
|
-
}
|
|
459
|
+
if (mode === LAUNCHER_MODES.KING) installTelegramForProfile(PKG, blunDir);
|
|
1024
460
|
|
|
1025
461
|
const nativeModules = repairConfiguredNativeModules({
|
|
1026
462
|
blunDir,
|
|
@@ -1033,7 +469,6 @@ async function runLauncher(options = {}) {
|
|
|
1033
469
|
process.stdout.write('Native Node.js-Module sind wieder einsatzbereit.\n');
|
|
1034
470
|
}
|
|
1035
471
|
|
|
1036
|
-
// --- 6. Start -----------------------------------------------------------
|
|
1037
472
|
const env = createLauncherEnvironment(process.env, mode, readPackageVersion());
|
|
1038
473
|
env.BLUN_HOME = profilePaths.home;
|
|
1039
474
|
env.BLUN_SHARED_HOME = privatePaths.sharedHome;
|
|
@@ -1051,31 +486,21 @@ async function runLauncher(options = {}) {
|
|
|
1051
486
|
ARGS,
|
|
1052
487
|
env,
|
|
1053
488
|
callerCwd,
|
|
1054
|
-
|
|
1055
|
-
{ startupPendingRuntime, staleActiveRuntime },
|
|
489
|
+
releaseLauncherLeases,
|
|
1056
490
|
);
|
|
1057
491
|
} finally {
|
|
1058
492
|
await mnemoConnect.stop();
|
|
1059
493
|
}
|
|
1060
494
|
} finally {
|
|
1061
|
-
await
|
|
495
|
+
await releaseLauncherLeases();
|
|
1062
496
|
}
|
|
1063
497
|
}
|
|
1064
498
|
|
|
1065
499
|
module.exports = {
|
|
1066
|
-
RUNNING_UPDATE_ERROR_RETRY_MS,
|
|
1067
|
-
RUNNING_UPDATE_RECHECK_JITTER_MS,
|
|
1068
|
-
RUNNING_UPDATE_RECHECK_MS,
|
|
1069
|
-
RUNNING_UPDATE_STABILIZATION_MS,
|
|
1070
500
|
createManagedNodeEnvironment,
|
|
1071
|
-
prepareAutomaticStartupRuntime,
|
|
1072
501
|
resolveLauncherPrivatePaths,
|
|
1073
|
-
resolveHandoffCwd,
|
|
1074
|
-
runningUpdateRecheckDelay,
|
|
1075
502
|
runLauncher,
|
|
1076
|
-
|
|
1077
|
-
shouldLaunchPreparedRuntimeAutomatically,
|
|
1078
|
-
shouldRecoverActivatedRuntime,
|
|
503
|
+
shouldResumeAfterStartupUpdate,
|
|
1079
504
|
shouldDetachProtectedCore,
|
|
1080
505
|
spawnManagedLauncher,
|
|
1081
506
|
superviseProtectedCore,
|