blun-king-cli 9.1.485 → 9.1.486
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 +7 -10
- package/README.md +6 -5
- package/bin/launcher-runtime.js +13 -0
- package/bin/startup-preferences.cjs +130 -0
- package/bin/update-notice.js +104 -43
- package/blun.mjs +12 -1
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
|
@@ -20,16 +20,13 @@ Start
|
|
|
20
20
|
Beide Startbefehle verwenden dieselbe Version, dasselbe Konto, dasselbe Modell
|
|
21
21
|
und dieselben Befehle.
|
|
22
22
|
|
|
23
|
-
king und king -c prüfen beim interaktiven Start auf eine neuere Version.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Es gibt keinen Download und keine Installation im Hintergrund. Nach einer
|
|
31
|
-
gewählten Installation endet king; king -c setzt die letzte Sitzung mit der
|
|
32
|
-
neuen Version fort.
|
|
23
|
+
king und king -c prüfen beim interaktiven Start auf eine neuere Version.
|
|
24
|
+
Automatische Updates sind standardmäßig aktiv und installieren den geprüften
|
|
25
|
+
Zielstand ohne zusätzliche Bestätigung. Danach endet king; king -c setzt die
|
|
26
|
+
letzte Sitzung mit der neuen Version fort. Mit
|
|
27
|
+
[upgrade].auto_install = false in tui.toml erscheint stattdessen der sichtbare
|
|
28
|
+
Auswahldialog. Start- und Update-Meldungen sind bei einer neuen Installation
|
|
29
|
+
standardmäßig Englisch; eine ausdrücklich gewählte Sprache bleibt erhalten.
|
|
33
30
|
|
|
34
31
|
Standard-MCPs und Eingabesteuerung
|
|
35
32
|
---------------------------------
|
package/README.md
CHANGED
|
@@ -36,11 +36,12 @@ gilt nur für den laufenden Prozess; die gespeicherte
|
|
|
36
36
|
Plugin-Konfiguration wird nicht umgeschrieben.
|
|
37
37
|
|
|
38
38
|
`king` und `king -c` prüfen beim interaktiven Start, ob eine neuere Version
|
|
39
|
-
vorliegt.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
vorliegt. Automatische Updates sind standardmäßig aktiv und installieren den
|
|
40
|
+
geprüften Zielstand ohne zusätzliche Bestätigung. Danach endet `king`; `king -c`
|
|
41
|
+
setzt die letzte Sitzung mit der neuen Version fort. Mit
|
|
42
|
+
`[upgrade].auto_install = false` in `tui.toml` erscheint stattdessen der sichtbare
|
|
43
|
+
Auswahldialog. Start- und Update-Meldungen sind bei einer neuen Installation
|
|
44
|
+
standardmäßig Englisch; eine ausdrücklich gewählte Sprache bleibt erhalten.
|
|
44
45
|
|
|
45
46
|
Telegram-Chats werden ohne manuell eingegebene IDs verbunden. In der Konsole
|
|
46
47
|
erzeugt `/telegram:access connect` einen einmaligen Code. `/connect CODE` im
|
package/bin/launcher-runtime.js
CHANGED
|
@@ -42,6 +42,11 @@ const {
|
|
|
42
42
|
resolveProfilePaths,
|
|
43
43
|
seedDefaultProfileFromLegacy,
|
|
44
44
|
} = require('./profile-runtime.cjs');
|
|
45
|
+
const {
|
|
46
|
+
migrateLegacyStartupPreferences,
|
|
47
|
+
readStartupPreferences,
|
|
48
|
+
resolveStartupUiLocale,
|
|
49
|
+
} = require('./startup-preferences.cjs');
|
|
45
50
|
|
|
46
51
|
const PKG = path.resolve(__dirname, '..');
|
|
47
52
|
const RAW_ARGS = process.argv.slice(2);
|
|
@@ -398,6 +403,9 @@ async function runLauncher(options = {}) {
|
|
|
398
403
|
if (explicitUpdateRequest) {
|
|
399
404
|
const privatePaths = getPrivatePaths();
|
|
400
405
|
ensurePrivateDirectory(privatePaths.sharedHome);
|
|
406
|
+
ensurePrivateDirectory(privatePaths.profilePaths.home);
|
|
407
|
+
migrateLegacyStartupPreferences(privatePaths.profilePaths.home);
|
|
408
|
+
const startupPreferences = readStartupPreferences(privatePaths.profilePaths.home);
|
|
401
409
|
const result = await runExplicitUpdate({
|
|
402
410
|
currentVersion: readPackageVersion(),
|
|
403
411
|
env: process.env,
|
|
@@ -405,6 +413,7 @@ async function runLauncher(options = {}) {
|
|
|
405
413
|
stdout: process.stdout,
|
|
406
414
|
stderr: process.stderr,
|
|
407
415
|
blunDir: privatePaths.sharedHome,
|
|
416
|
+
uiLocale: resolveStartupUiLocale(startupPreferences.uiLocale, process.env),
|
|
408
417
|
packageRoot: PKG,
|
|
409
418
|
noticeLease: launcherLease,
|
|
410
419
|
});
|
|
@@ -449,6 +458,8 @@ async function runLauncher(options = {}) {
|
|
|
449
458
|
}
|
|
450
459
|
const blunDir = profilePaths.home;
|
|
451
460
|
ensurePrivateDirectory(blunDir);
|
|
461
|
+
migrateLegacyStartupPreferences(blunDir);
|
|
462
|
+
const startupPreferences = readStartupPreferences(blunDir);
|
|
452
463
|
|
|
453
464
|
const updateResult = await runUpdateNotice({
|
|
454
465
|
currentVersion: readPackageVersion(),
|
|
@@ -458,6 +469,8 @@ async function runLauncher(options = {}) {
|
|
|
458
469
|
stdout: process.stdout,
|
|
459
470
|
stderr: process.stderr,
|
|
460
471
|
blunDir: privatePaths.sharedHome,
|
|
472
|
+
autoInstall: startupPreferences.autoInstall,
|
|
473
|
+
uiLocale: resolveStartupUiLocale(startupPreferences.uiLocale, process.env),
|
|
461
474
|
packageRoot: PKG,
|
|
462
475
|
noticeLease: launcherLease,
|
|
463
476
|
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const CONFIG_FILE = 'tui.toml';
|
|
7
|
+
const MIGRATION_MARKER = '.legacy-auto-ui-locale-v1';
|
|
8
|
+
const MIGRATION_BACKUP = 'tui.toml.vor-english-default-v1';
|
|
9
|
+
const MAX_CONFIG_BYTES = 256 * 1024;
|
|
10
|
+
|
|
11
|
+
function safeConfigPath(profileHome, fsImpl = fs) {
|
|
12
|
+
const configPath = path.join(path.resolve(profileHome), CONFIG_FILE);
|
|
13
|
+
if (!fsImpl.existsSync(configPath)) return undefined;
|
|
14
|
+
const stat = fsImpl.lstatSync(configPath);
|
|
15
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_CONFIG_BYTES) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return configPath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseStartupPreferences(text) {
|
|
22
|
+
let section = '';
|
|
23
|
+
let autoInstall = true;
|
|
24
|
+
let uiLocale = 'en';
|
|
25
|
+
|
|
26
|
+
for (const line of String(text).replace(/^\uFEFF/u, '').split(/\r?\n/u)) {
|
|
27
|
+
const sectionMatch = /^\s*\[([^\]]+)\]\s*(?:#.*)?$/u.exec(line);
|
|
28
|
+
if (sectionMatch) {
|
|
29
|
+
section = sectionMatch[1].trim().toLowerCase();
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (section === '') {
|
|
33
|
+
const localeMatch = /^\s*ui_locale\s*=\s*"([^"]+)"\s*(?:#.*)?$/u.exec(line);
|
|
34
|
+
if (localeMatch && /^(?:auto|[a-z]{2}(?:-[a-z0-9]+)*)$/iu.test(localeMatch[1])) {
|
|
35
|
+
uiLocale = localeMatch[1].toLowerCase();
|
|
36
|
+
}
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (section === 'upgrade') {
|
|
40
|
+
const automaticMatch = /^\s*auto_install\s*=\s*(true|false)\s*(?:#.*)?$/iu.exec(line);
|
|
41
|
+
if (automaticMatch) autoInstall = automaticMatch[1].toLowerCase() === 'true';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { autoInstall, uiLocale };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function readStartupPreferences(profileHome, fsImpl = fs) {
|
|
49
|
+
const configPath = safeConfigPath(profileHome, fsImpl);
|
|
50
|
+
if (!configPath) return { autoInstall: true, uiLocale: 'en' };
|
|
51
|
+
try {
|
|
52
|
+
return parseStartupPreferences(fsImpl.readFileSync(configPath, 'utf8'));
|
|
53
|
+
} catch {
|
|
54
|
+
return { autoInstall: true, uiLocale: 'en' };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveStartupUiLocale(uiLocale, env = process.env) {
|
|
59
|
+
const normalized = String(uiLocale || 'en').trim().toLowerCase();
|
|
60
|
+
if (normalized !== 'auto') return normalized;
|
|
61
|
+
const operatingSystemLocale = String(env.LC_ALL || env.LC_MESSAGES || env.LANG || '')
|
|
62
|
+
.trim()
|
|
63
|
+
.toLowerCase();
|
|
64
|
+
return operatingSystemLocale === 'de'
|
|
65
|
+
|| operatingSystemLocale.startsWith('de-')
|
|
66
|
+
|| operatingSystemLocale.startsWith('de_')
|
|
67
|
+
|| operatingSystemLocale.startsWith('de.')
|
|
68
|
+
? 'de'
|
|
69
|
+
: 'en';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function writeMarkerOnce(markerPath, fsImpl) {
|
|
73
|
+
try {
|
|
74
|
+
fsImpl.writeFileSync(markerPath, 'legacy automatic UI locale reviewed once\n', {
|
|
75
|
+
encoding: 'utf8',
|
|
76
|
+
flag: 'wx',
|
|
77
|
+
});
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error?.code !== 'EEXIST') throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function replaceIfUnchanged(target, original, replacement, fsImpl) {
|
|
84
|
+
if (fsImpl.readFileSync(target, 'utf8') !== original) {
|
|
85
|
+
throw new Error(`Startup preferences changed during migration: ${target}`);
|
|
86
|
+
}
|
|
87
|
+
const temporary = `${target}.migration-${process.pid}-${Date.now()}.tmp`;
|
|
88
|
+
fsImpl.writeFileSync(temporary, replacement, 'utf8');
|
|
89
|
+
try {
|
|
90
|
+
fsImpl.renameSync(temporary, target);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
try {
|
|
93
|
+
fsImpl.rmSync(temporary, { force: true });
|
|
94
|
+
} catch {}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function migrateLegacyStartupPreferences(profileHome, fsImpl = fs) {
|
|
100
|
+
const resolvedHome = path.resolve(profileHome);
|
|
101
|
+
fsImpl.mkdirSync(resolvedHome, { recursive: true });
|
|
102
|
+
const markerPath = path.join(resolvedHome, MIGRATION_MARKER);
|
|
103
|
+
const backupPath = path.join(resolvedHome, MIGRATION_BACKUP);
|
|
104
|
+
if (fsImpl.existsSync(markerPath)) return { changed: false };
|
|
105
|
+
|
|
106
|
+
const configPath = safeConfigPath(resolvedHome, fsImpl);
|
|
107
|
+
if (!configPath) {
|
|
108
|
+
writeMarkerOnce(markerPath, fsImpl);
|
|
109
|
+
return { changed: false };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const original = fsImpl.readFileSync(configPath, 'utf8');
|
|
113
|
+
const legacyLocale = /^(\s*ui_locale\s*=\s*)"auto"(\s*(?:#.*)?)$/mu;
|
|
114
|
+
if (!legacyLocale.test(original)) {
|
|
115
|
+
writeMarkerOnce(markerPath, fsImpl);
|
|
116
|
+
return { changed: false };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!fsImpl.existsSync(backupPath)) fsImpl.copyFileSync(configPath, backupPath);
|
|
120
|
+
const replacement = original.replace(legacyLocale, '$1"en"$2');
|
|
121
|
+
replaceIfUnchanged(configPath, original, replacement, fsImpl);
|
|
122
|
+
writeMarkerOnce(markerPath, fsImpl);
|
|
123
|
+
return { backupPath, changed: true };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = {
|
|
127
|
+
migrateLegacyStartupPreferences,
|
|
128
|
+
readStartupPreferences,
|
|
129
|
+
resolveStartupUiLocale,
|
|
130
|
+
};
|
package/bin/update-notice.js
CHANGED
|
@@ -621,6 +621,54 @@ function installCommandText(version) {
|
|
|
621
621
|
return `npm i -g ${PACKAGE_NAME}@${version}`;
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
+
function updateCopy(uiLocale) {
|
|
625
|
+
const german = String(uiLocale || '').toLowerCase().startsWith('de');
|
|
626
|
+
if (german) {
|
|
627
|
+
return {
|
|
628
|
+
available: (current, next) => `BLUN Code-Update verfügbar: ${current} -> ${next}`,
|
|
629
|
+
current: (version) => `Kein Update verfügbar. Installiert: ${version} · Aktuell: ${version}.`,
|
|
630
|
+
enter: 'Enter drücken, um fortzufahren',
|
|
631
|
+
failed: (code) => `Update fehlgeschlagen (Code ${code}).`,
|
|
632
|
+
install: (version) => `Jetzt aktualisieren (führt \`${installCommandText(version)}\` aus)`,
|
|
633
|
+
installFailed: (code) => `Update fehlgeschlagen (Code ${code}). Die vorhandene Version wird gestartet.`,
|
|
634
|
+
installed: 'Installation geprüft',
|
|
635
|
+
installedContinue: (current, next) => `Update ${current} -> ${next} erfolgreich installiert. Die letzte Sitzung wird mit der neuen Version fortgesetzt.`,
|
|
636
|
+
installedRestart: (current, next) => `Update ${current} -> ${next} erfolgreich installiert. Starte BLUN Code neu, um die neue Version zu verwenden.`,
|
|
637
|
+
installerReady: 'Installer bereit',
|
|
638
|
+
installing: 'Paket wird installiert',
|
|
639
|
+
invalidTarget: (version) => `Kein sicherer Update-Zielstand verfügbar. Installiert: ${version}.`,
|
|
640
|
+
nextRelease: 'Auf den nächsten Release warten',
|
|
641
|
+
notes: 'Versionshinweise',
|
|
642
|
+
skip: 'Überspringen',
|
|
643
|
+
startupNoticeFailed: (version) => `Update ${version} wurde installiert, aber die Startmeldung konnte nicht gespeichert werden.`,
|
|
644
|
+
updateChecked: 'Update geprüft',
|
|
645
|
+
verificationFailed: 'Das Update konnte nicht verifiziert werden.',
|
|
646
|
+
verificationRestart: 'Update konnte nicht verifiziert werden. Starte BLUN Code neu.',
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
return {
|
|
650
|
+
available: (current, next) => `BLUN Code update available: ${current} -> ${next}`,
|
|
651
|
+
current: (version) => `No update available. Installed: ${version} · Current: ${version}.`,
|
|
652
|
+
enter: 'Press Enter to continue',
|
|
653
|
+
failed: (code) => `Update failed (code ${code}).`,
|
|
654
|
+
install: (version) => `Update now (runs \`${installCommandText(version)}\`)`,
|
|
655
|
+
installFailed: (code) => `Update failed (code ${code}). The installed version will start.`,
|
|
656
|
+
installed: 'Installation verified',
|
|
657
|
+
installedContinue: (current, next) => `Update ${current} -> ${next} installed successfully. The last session will continue with the new version.`,
|
|
658
|
+
installedRestart: (current, next) => `Update ${current} -> ${next} installed successfully. Restart BLUN Code to use the new version.`,
|
|
659
|
+
installerReady: 'Installer ready',
|
|
660
|
+
installing: 'Installing package',
|
|
661
|
+
invalidTarget: (version) => `No safe update target is available. Installed: ${version}.`,
|
|
662
|
+
nextRelease: 'Wait for the next release',
|
|
663
|
+
notes: 'Release notes',
|
|
664
|
+
skip: 'Skip',
|
|
665
|
+
startupNoticeFailed: (version) => `Update ${version} was installed, but the startup notice could not be saved.`,
|
|
666
|
+
updateChecked: 'Update checked',
|
|
667
|
+
verificationFailed: 'The update could not be verified.',
|
|
668
|
+
verificationRestart: 'The update could not be verified. Restart BLUN Code.',
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
624
672
|
function createUpdateProgress(output) {
|
|
625
673
|
const enabled = output?.isTTY === true;
|
|
626
674
|
const phaseCount = 4;
|
|
@@ -646,7 +694,14 @@ function createUpdateProgress(output) {
|
|
|
646
694
|
return update;
|
|
647
695
|
}
|
|
648
696
|
|
|
649
|
-
function promptUpdateAction({
|
|
697
|
+
function promptUpdateAction({
|
|
698
|
+
currentVersion,
|
|
699
|
+
release,
|
|
700
|
+
input,
|
|
701
|
+
output,
|
|
702
|
+
processRef = process,
|
|
703
|
+
uiLocale = 'en',
|
|
704
|
+
}) {
|
|
650
705
|
return new Promise((resolve, reject) => {
|
|
651
706
|
let selected = 0;
|
|
652
707
|
let settled = false;
|
|
@@ -659,13 +714,14 @@ function promptUpdateAction({ currentVersion, release, input, output, processRef
|
|
|
659
714
|
const dim = '\u001B[2m';
|
|
660
715
|
const underline = '\u001B[4m';
|
|
661
716
|
const reset = '\u001B[0m';
|
|
717
|
+
const copy = updateCopy(uiLocale);
|
|
662
718
|
const actions = [
|
|
663
719
|
{
|
|
664
720
|
choice: 'install',
|
|
665
|
-
label:
|
|
721
|
+
label: copy.install(release.version),
|
|
666
722
|
},
|
|
667
|
-
{ choice: 'skip-once', label:
|
|
668
|
-
{ choice: 'skip-version', label:
|
|
723
|
+
{ choice: 'skip-once', label: copy.skip },
|
|
724
|
+
{ choice: 'skip-version', label: copy.nextRelease },
|
|
669
725
|
];
|
|
670
726
|
const signalHandlers = new Map();
|
|
671
727
|
|
|
@@ -675,7 +731,7 @@ function promptUpdateAction({ currentVersion, release, input, output, processRef
|
|
|
675
731
|
const line = `${selected === index ? '›' : ' '} ${index + 1}. ${actions[index].label}`;
|
|
676
732
|
output.write(`\r\u001B[2K${selected === index ? cyan : ''}${line}${selected === index ? reset : ''}\n`);
|
|
677
733
|
}
|
|
678
|
-
output.write(`\r\u001B[2K${dim}
|
|
734
|
+
output.write(`\r\u001B[2K${dim}${copy.enter}${reset}\n`);
|
|
679
735
|
};
|
|
680
736
|
const cleanup = () => {
|
|
681
737
|
if (escapeTimer !== undefined) clearTimeout(escapeTimer);
|
|
@@ -830,9 +886,9 @@ function promptUpdateAction({ currentVersion, release, input, output, processRef
|
|
|
830
886
|
signalHandlers.set(signal, handler);
|
|
831
887
|
processRef.once(signal, handler);
|
|
832
888
|
}
|
|
833
|
-
output.write(`\
|
|
889
|
+
output.write(`\n${copy.available(currentVersion, release.version)}\n`);
|
|
834
890
|
if (release.notesUrl) {
|
|
835
|
-
output.write(`${dim}
|
|
891
|
+
output.write(`${dim}${copy.notes}:${reset} ${underline}${release.notesUrl}${reset}\n`);
|
|
836
892
|
}
|
|
837
893
|
output.write('\n');
|
|
838
894
|
cursorHidden = true;
|
|
@@ -1290,19 +1346,21 @@ function noReleaseReason(currentVersion, registryTags, fallbackManifest) {
|
|
|
1290
1346
|
return parseSemver(latest) || fallbackManifest ? 'current' : 'unavailable';
|
|
1291
1347
|
}
|
|
1292
1348
|
|
|
1293
|
-
function explicitNoTarget(stdout, reason, currentVersion) {
|
|
1349
|
+
function explicitNoTarget(stdout, reason, currentVersion, uiLocale) {
|
|
1350
|
+
const copy = updateCopy(uiLocale);
|
|
1294
1351
|
stdout.write(reason === 'current'
|
|
1295
|
-
?
|
|
1296
|
-
:
|
|
1352
|
+
? `${copy.current(currentVersion)}\n`
|
|
1353
|
+
: `${copy.invalidTarget(currentVersion)}\n`);
|
|
1297
1354
|
return { kind: 'current', reason };
|
|
1298
1355
|
}
|
|
1299
1356
|
|
|
1300
|
-
function explicitFailure(stderr, reason, exitCode) {
|
|
1357
|
+
function explicitFailure(stderr, reason, exitCode, uiLocale) {
|
|
1358
|
+
const copy = updateCopy(uiLocale);
|
|
1301
1359
|
const hasExitCode = Number.isInteger(exitCode) && exitCode !== 0;
|
|
1302
1360
|
if (hasExitCode) {
|
|
1303
|
-
stderr.write(
|
|
1361
|
+
stderr.write(`${copy.failed(exitCode)}\n`);
|
|
1304
1362
|
} else {
|
|
1305
|
-
stderr.write(
|
|
1363
|
+
stderr.write(`${copy.verificationFailed}\n`);
|
|
1306
1364
|
}
|
|
1307
1365
|
return {
|
|
1308
1366
|
kind: 'failed',
|
|
@@ -1321,12 +1379,14 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1321
1379
|
stderr,
|
|
1322
1380
|
blunDir,
|
|
1323
1381
|
} = options;
|
|
1382
|
+
const uiLocale = options.uiLocale || 'en';
|
|
1383
|
+
const copy = updateCopy(uiLocale);
|
|
1324
1384
|
if (!explicitUpdate && !isInteractiveUpdateStart({ argv, env, stdin, stdout })) {
|
|
1325
1385
|
return { kind: 'continue', reason: 'not_interactive' };
|
|
1326
1386
|
}
|
|
1327
1387
|
if (!parseSemver(currentVersion)) {
|
|
1328
1388
|
return explicitUpdate
|
|
1329
|
-
? explicitFailure(stderr, 'invalid_current_version')
|
|
1389
|
+
? explicitFailure(stderr, 'invalid_current_version', undefined, uiLocale)
|
|
1330
1390
|
: { kind: 'continue', reason: 'invalid_current_version' };
|
|
1331
1391
|
}
|
|
1332
1392
|
|
|
@@ -1340,7 +1400,7 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1340
1400
|
leaseResult = await (options.acquireLease || tryAcquireUpdateLease)({ packageRoot });
|
|
1341
1401
|
} catch {
|
|
1342
1402
|
return explicitUpdate
|
|
1343
|
-
? explicitFailure(stderr, 'lease_unavailable')
|
|
1403
|
+
? explicitFailure(stderr, 'lease_unavailable', undefined, uiLocale)
|
|
1344
1404
|
: { kind: 'continue', reason: 'lease_unavailable' };
|
|
1345
1405
|
}
|
|
1346
1406
|
} else {
|
|
@@ -1351,6 +1411,8 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1351
1411
|
return explicitFailure(
|
|
1352
1412
|
stderr,
|
|
1353
1413
|
leaseResult?.reason === 'busy' ? 'update_in_progress' : 'lease_unavailable',
|
|
1414
|
+
undefined,
|
|
1415
|
+
uiLocale,
|
|
1354
1416
|
);
|
|
1355
1417
|
}
|
|
1356
1418
|
return leaseResult?.reason === 'busy'
|
|
@@ -1366,7 +1428,7 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1366
1428
|
sources = await (options.loadReleaseSources || loadReleaseSources)();
|
|
1367
1429
|
} catch {
|
|
1368
1430
|
return explicitUpdate
|
|
1369
|
-
? explicitNoTarget(stdout, 'unavailable', currentVersion)
|
|
1431
|
+
? explicitNoTarget(stdout, 'unavailable', currentVersion, uiLocale)
|
|
1370
1432
|
: { kind: 'continue', reason: 'unavailable' };
|
|
1371
1433
|
}
|
|
1372
1434
|
const registryTags = parseRegistryDocument(sources?.registryDocument);
|
|
@@ -1375,7 +1437,7 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1375
1437
|
if (!release) {
|
|
1376
1438
|
const reason = noReleaseReason(currentVersion, registryTags, fallbackManifest);
|
|
1377
1439
|
return explicitUpdate
|
|
1378
|
-
? explicitNoTarget(stdout, reason, currentVersion)
|
|
1440
|
+
? explicitNoTarget(stdout, reason, currentVersion, uiLocale)
|
|
1379
1441
|
: { kind: 'continue', reason };
|
|
1380
1442
|
}
|
|
1381
1443
|
if (!explicitUpdate
|
|
@@ -1385,12 +1447,12 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1385
1447
|
const initialInstallLease = await probeInstallLease(options, packageRoot);
|
|
1386
1448
|
if (initialInstallLease === 'busy') {
|
|
1387
1449
|
return explicitUpdate
|
|
1388
|
-
? explicitFailure(stderr, 'update_in_progress')
|
|
1450
|
+
? explicitFailure(stderr, 'update_in_progress', undefined, uiLocale)
|
|
1389
1451
|
: { kind: 'update_in_progress' };
|
|
1390
1452
|
}
|
|
1391
1453
|
if (initialInstallLease !== 'clear') {
|
|
1392
1454
|
return explicitUpdate
|
|
1393
|
-
? explicitFailure(stderr, 'lease_unavailable')
|
|
1455
|
+
? explicitFailure(stderr, 'lease_unavailable', undefined, uiLocale)
|
|
1394
1456
|
: { kind: 'continue', reason: 'lease_unavailable' };
|
|
1395
1457
|
}
|
|
1396
1458
|
if (!explicitUpdate
|
|
@@ -1401,25 +1463,25 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1401
1463
|
try {
|
|
1402
1464
|
ensurePrivateDirectory(blunDir);
|
|
1403
1465
|
} catch {
|
|
1404
|
-
return explicitFailure(stderr, 'private_home_unavailable');
|
|
1466
|
+
return explicitFailure(stderr, 'private_home_unavailable', undefined, uiLocale);
|
|
1405
1467
|
}
|
|
1406
1468
|
}
|
|
1407
1469
|
try {
|
|
1408
1470
|
lease.assertOwned();
|
|
1409
1471
|
} catch {
|
|
1410
1472
|
return explicitUpdate
|
|
1411
|
-
? explicitFailure(stderr, 'update_in_progress')
|
|
1473
|
+
? explicitFailure(stderr, 'update_in_progress', undefined, uiLocale)
|
|
1412
1474
|
: { kind: 'update_in_progress' };
|
|
1413
1475
|
}
|
|
1414
1476
|
const prePromptInstallLease = await probeInstallLease(options, packageRoot);
|
|
1415
1477
|
if (prePromptInstallLease === 'busy') {
|
|
1416
1478
|
return explicitUpdate
|
|
1417
|
-
? explicitFailure(stderr, 'update_in_progress')
|
|
1479
|
+
? explicitFailure(stderr, 'update_in_progress', undefined, uiLocale)
|
|
1418
1480
|
: { kind: 'update_in_progress' };
|
|
1419
1481
|
}
|
|
1420
1482
|
if (prePromptInstallLease !== 'clear') {
|
|
1421
1483
|
return explicitUpdate
|
|
1422
|
-
? explicitFailure(stderr, 'lease_unavailable')
|
|
1484
|
+
? explicitFailure(stderr, 'lease_unavailable', undefined, uiLocale)
|
|
1423
1485
|
: { kind: 'continue', reason: 'lease_unavailable' };
|
|
1424
1486
|
}
|
|
1425
1487
|
if (!options.installVersion) {
|
|
@@ -1429,7 +1491,7 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1429
1491
|
);
|
|
1430
1492
|
if (!installerSession?.ready) {
|
|
1431
1493
|
if (explicitUpdate) {
|
|
1432
|
-
return explicitFailure(stderr, 'installer_unavailable');
|
|
1494
|
+
return explicitFailure(stderr, 'installer_unavailable', undefined, uiLocale);
|
|
1433
1495
|
}
|
|
1434
1496
|
return installerSession?.reason === 'failed'
|
|
1435
1497
|
? { kind: 'continue', reason: 'installer_unavailable' }
|
|
@@ -1437,7 +1499,7 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1437
1499
|
}
|
|
1438
1500
|
}
|
|
1439
1501
|
let action;
|
|
1440
|
-
if (explicitUpdate) {
|
|
1502
|
+
if (explicitUpdate || options.autoInstall === true) {
|
|
1441
1503
|
action = 'install';
|
|
1442
1504
|
} else {
|
|
1443
1505
|
try {
|
|
@@ -1446,6 +1508,7 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1446
1508
|
release,
|
|
1447
1509
|
input: stdin,
|
|
1448
1510
|
output: stdout,
|
|
1511
|
+
uiLocale,
|
|
1449
1512
|
});
|
|
1450
1513
|
} catch {
|
|
1451
1514
|
return { kind: 'continue', reason: 'prompt_failed' };
|
|
@@ -1476,18 +1539,18 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1476
1539
|
}
|
|
1477
1540
|
|
|
1478
1541
|
const updateProgress = createUpdateProgress(stdout);
|
|
1479
|
-
updateProgress(1,
|
|
1480
|
-
updateProgress(2,
|
|
1542
|
+
updateProgress(1, copy.updateChecked);
|
|
1543
|
+
updateProgress(2, copy.installerReady);
|
|
1481
1544
|
|
|
1482
1545
|
try {
|
|
1483
1546
|
lease.assertOwned();
|
|
1484
1547
|
} catch {
|
|
1485
1548
|
return explicitUpdate
|
|
1486
|
-
? explicitFailure(stderr, 'update_in_progress')
|
|
1549
|
+
? explicitFailure(stderr, 'update_in_progress', undefined, uiLocale)
|
|
1487
1550
|
: { kind: 'update_in_progress' };
|
|
1488
1551
|
}
|
|
1489
1552
|
let installResult;
|
|
1490
|
-
updateProgress(3,
|
|
1553
|
+
updateProgress(3, copy.installing);
|
|
1491
1554
|
try {
|
|
1492
1555
|
installResult = options.installVersion
|
|
1493
1556
|
? await options.installVersion(release.version)
|
|
@@ -1500,11 +1563,11 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1500
1563
|
|| installResult?.unknownState === true) {
|
|
1501
1564
|
updateProgress.finish();
|
|
1502
1565
|
return explicitUpdate
|
|
1503
|
-
? explicitFailure(stderr, 'update_in_progress')
|
|
1566
|
+
? explicitFailure(stderr, 'update_in_progress', undefined, uiLocale)
|
|
1504
1567
|
: { kind: 'update_in_progress' };
|
|
1505
1568
|
}
|
|
1506
1569
|
if (installResult?.code === 0 && installResult?.verified === true) {
|
|
1507
|
-
updateProgress(4,
|
|
1570
|
+
updateProgress(4, copy.installed);
|
|
1508
1571
|
clearPendingUpdate(blunDir);
|
|
1509
1572
|
try {
|
|
1510
1573
|
writeCoreInstallSuccess(
|
|
@@ -1512,21 +1575,19 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1512
1575
|
currentVersion,
|
|
1513
1576
|
release.version,
|
|
1514
1577
|
release.releaseNotes,
|
|
1515
|
-
explicitUpdate ? 'manual' : 'startup_prompt',
|
|
1578
|
+
explicitUpdate ? 'manual' : options.autoInstall === true ? 'startup_auto' : 'startup_prompt',
|
|
1516
1579
|
(options.now || Date.now)(),
|
|
1517
1580
|
);
|
|
1518
1581
|
} catch {
|
|
1519
|
-
stderr.write(
|
|
1520
|
-
`Update ${release.version} wurde installiert, aber die Startmeldung konnte nicht gespeichert werden.\n`,
|
|
1521
|
-
);
|
|
1582
|
+
stderr.write(`${copy.startupNoticeFailed(release.version)}\n`);
|
|
1522
1583
|
}
|
|
1523
1584
|
const continuesLastSession = Array.isArray(options.argv)
|
|
1524
1585
|
&& options.argv.length === 1
|
|
1525
1586
|
&& options.argv[0] === '-c';
|
|
1526
|
-
stdout.write(continuesLastSession
|
|
1527
|
-
?
|
|
1528
|
-
:
|
|
1529
|
-
if (release.notesUrl) stdout.write(
|
|
1587
|
+
stdout.write(`${continuesLastSession
|
|
1588
|
+
? copy.installedContinue(currentVersion, release.version)
|
|
1589
|
+
: copy.installedRestart(currentVersion, release.version)}\n`);
|
|
1590
|
+
if (release.notesUrl) stdout.write(`${copy.notes}: ${release.notesUrl}\n`);
|
|
1530
1591
|
return {
|
|
1531
1592
|
kind: 'installed',
|
|
1532
1593
|
version: release.version,
|
|
@@ -1536,14 +1597,14 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1536
1597
|
if (Number.isInteger(installResult?.code) && installResult.code !== 0) {
|
|
1537
1598
|
updateProgress.finish();
|
|
1538
1599
|
if (explicitUpdate) {
|
|
1539
|
-
return explicitFailure(stderr, 'install_failed', installResult.code);
|
|
1600
|
+
return explicitFailure(stderr, 'install_failed', installResult.code, uiLocale);
|
|
1540
1601
|
}
|
|
1541
|
-
stderr.write(
|
|
1602
|
+
stderr.write(`${copy.installFailed(installResult.code)}\n`);
|
|
1542
1603
|
return { kind: 'continue', reason: 'install_failed', exitCode: installResult.code };
|
|
1543
1604
|
}
|
|
1544
1605
|
updateProgress.finish();
|
|
1545
|
-
if (explicitUpdate) return explicitFailure(stderr, 'verification_failed');
|
|
1546
|
-
stderr.write(
|
|
1606
|
+
if (explicitUpdate) return explicitFailure(stderr, 'verification_failed', undefined, uiLocale);
|
|
1607
|
+
stderr.write(`${copy.verificationRestart}\n`);
|
|
1547
1608
|
return { kind: 'update_in_progress' };
|
|
1548
1609
|
} finally {
|
|
1549
1610
|
if (installerSession?.ready) {
|
package/blun.mjs
CHANGED
|
@@ -342525,6 +342525,7 @@ const NotificationsConfigSchema = object({
|
|
|
342525
342525
|
enabled: boolean$1(),
|
|
342526
342526
|
condition: NotificationConditionSchema
|
|
342527
342527
|
});
|
|
342528
|
+
const UpgradePreferencesSchema = object({ autoInstall: boolean$1() });
|
|
342528
342529
|
const InlineSuggestConfigSchema = object({ languages: record(string(), boolean$1()) });
|
|
342529
342530
|
const HexColorSchema = string().regex(/^#[0-9A-Fa-f]{6}$/u);
|
|
342530
342531
|
const AppearanceConfigSchema = object({
|
|
@@ -342541,7 +342542,8 @@ const TuiConfigFileSchema = object({
|
|
|
342541
342542
|
notifications: object({
|
|
342542
342543
|
enabled: boolean$1().optional(),
|
|
342543
342544
|
notification_condition: NotificationConditionSchema.optional()
|
|
342544
|
-
}).optional()
|
|
342545
|
+
}).optional(),
|
|
342546
|
+
upgrade: object({ auto_install: boolean$1().optional() }).optional()
|
|
342545
342547
|
});
|
|
342546
342548
|
const TuiConfigSchema = object({
|
|
342547
342549
|
theme: TuiThemeSchema,
|
|
@@ -342550,12 +342552,14 @@ const TuiConfigSchema = object({
|
|
|
342550
342552
|
disablePasteBurst: boolean$1(),
|
|
342551
342553
|
editorCommand: string().nullable(),
|
|
342552
342554
|
notifications: NotificationsConfigSchema,
|
|
342555
|
+
upgrade: UpgradePreferencesSchema,
|
|
342553
342556
|
inlineSuggest: InlineSuggestConfigSchema
|
|
342554
342557
|
});
|
|
342555
342558
|
const DEFAULT_NOTIFICATIONS_CONFIG = {
|
|
342556
342559
|
enabled: true,
|
|
342557
342560
|
condition: "unfocused"
|
|
342558
342561
|
};
|
|
342562
|
+
const DEFAULT_UPGRADE_PREFERENCES = { autoInstall: true };
|
|
342559
342563
|
/**
|
|
342560
342564
|
* F2 Tippen-mit-Vorschlag: Code-Sprachen standardmäßig an, md/plain aus.
|
|
342561
342565
|
* Unbekannte Sprachen fallen auf "an" zurück (Opt-out über tui.toml).
|
|
@@ -342573,6 +342577,7 @@ const DEFAULT_TUI_CONFIG = TuiConfigSchema.parse({
|
|
|
342573
342577
|
disablePasteBurst: false,
|
|
342574
342578
|
editorCommand: null,
|
|
342575
342579
|
notifications: DEFAULT_NOTIFICATIONS_CONFIG,
|
|
342580
|
+
upgrade: DEFAULT_UPGRADE_PREFERENCES,
|
|
342576
342581
|
inlineSuggest: { languages: DEFAULT_INLINE_SUGGEST_LANGUAGES }
|
|
342577
342582
|
});
|
|
342578
342583
|
/**
|
|
@@ -342649,6 +342654,7 @@ function normalizeTuiConfig(config) {
|
|
|
342649
342654
|
enabled: config.notifications?.enabled ?? DEFAULT_NOTIFICATIONS_CONFIG.enabled,
|
|
342650
342655
|
condition: config.notifications?.notification_condition ?? DEFAULT_NOTIFICATIONS_CONFIG.condition
|
|
342651
342656
|
},
|
|
342657
|
+
upgrade: { autoInstall: config.upgrade?.auto_install ?? DEFAULT_UPGRADE_PREFERENCES.autoInstall },
|
|
342652
342658
|
inlineSuggest: { languages: {
|
|
342653
342659
|
...DEFAULT_INLINE_SUGGEST_LANGUAGES,
|
|
342654
342660
|
...config.inline_suggest?.languages
|
|
@@ -342673,6 +342679,9 @@ command = "${escapeTomlBasicString(config.editorCommand ?? "")}" # Empty uses $V
|
|
|
342673
342679
|
enabled = ${String(config.notifications.enabled)} # true | false
|
|
342674
342680
|
notification_condition = "${config.notifications.condition}" # "unfocused" | "always"
|
|
342675
342681
|
|
|
342682
|
+
[upgrade]
|
|
342683
|
+
auto_install = ${String(config.upgrade.autoInstall)} # true | false
|
|
342684
|
+
|
|
342676
342685
|
# F2 Tippen-mit-Vorschlag: Inline-Suggest je Sprache an/aus (wirkt ohne Neustart)
|
|
342677
342686
|
[inline_suggest.languages]
|
|
342678
342687
|
${renderInlineSuggestLanguages(config.inlineSuggest.languages)}
|
|
@@ -420717,6 +420726,7 @@ async function currentTuiConfig(host) {
|
|
|
420717
420726
|
editorCommand: host.state.appState.editorCommand,
|
|
420718
420727
|
disablePasteBurst: host.state.appState.disablePasteBurst ?? DEFAULT_TUI_CONFIG.disablePasteBurst,
|
|
420719
420728
|
notifications: host.state.appState.notifications,
|
|
420729
|
+
upgrade: host.state.appState.upgrade ?? DEFAULT_UPGRADE_PREFERENCES,
|
|
420720
420730
|
inlineSuggest
|
|
420721
420731
|
};
|
|
420722
420732
|
}
|
|
@@ -516915,6 +516925,7 @@ function createInitialAppState(input) {
|
|
|
516915
516925
|
editorCommand: input.tuiConfig.editorCommand,
|
|
516916
516926
|
disablePasteBurst: input.tuiConfig.disablePasteBurst,
|
|
516917
516927
|
notifications: input.tuiConfig.notifications,
|
|
516928
|
+
upgrade: input.tuiConfig.upgrade,
|
|
516918
516929
|
availableModels: {},
|
|
516919
516930
|
availableProviders: {},
|
|
516920
516931
|
sessionTitle: null,
|