blun-king-cli 9.1.485 → 9.1.488

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.
Files changed (99) hide show
  1. package/LIESMICH.txt +33 -17
  2. package/README.md +20 -8
  3. package/agent-spine-plugin/.claude-plugin/marketplace.json +20 -0
  4. package/agent-spine-plugin/.claude-plugin/plugin.json +14 -0
  5. package/agent-spine-plugin/.codex-plugin/plugin.json +34 -0
  6. package/agent-spine-plugin/.mcp.json +8 -0
  7. package/agent-spine-plugin/CHANGELOG.md +277 -0
  8. package/agent-spine-plugin/LICENSE +186 -0
  9. package/agent-spine-plugin/README.md +342 -0
  10. package/agent-spine-plugin/assets/agentspine-banner.svg +32 -0
  11. package/agent-spine-plugin/bin/agentspine-mcp.js +4 -0
  12. package/agent-spine-plugin/bin/agentspine.js +7 -0
  13. package/agent-spine-plugin/blun.plugin.json +33 -0
  14. package/agent-spine-plugin/docs/acceptance.md +61 -0
  15. package/agent-spine-plugin/docs/architecture.md +183 -0
  16. package/agent-spine-plugin/docs/attention.md +121 -0
  17. package/agent-spine-plugin/docs/automatic-continuity.md +79 -0
  18. package/agent-spine-plugin/docs/channel-runtime.md +92 -0
  19. package/agent-spine-plugin/docs/coordination.md +138 -0
  20. package/agent-spine-plugin/docs/feed-transport.md +99 -0
  21. package/agent-spine-plugin/docs/gateway-runtime.md +109 -0
  22. package/agent-spine-plugin/docs/harness-reference.md +45 -0
  23. package/agent-spine-plugin/docs/host-integration.md +129 -0
  24. package/agent-spine-plugin/docs/https-transport.md +116 -0
  25. package/agent-spine-plugin/docs/learning.md +98 -0
  26. package/agent-spine-plugin/docs/object-transport.md +93 -0
  27. package/agent-spine-plugin/docs/peer-transport.md +88 -0
  28. package/agent-spine-plugin/docs/preservation-contract.md +53 -0
  29. package/agent-spine-plugin/docs/quality-gates.md +50 -0
  30. package/agent-spine-plugin/docs/relationships.md +67 -0
  31. package/agent-spine-plugin/docs/releasing.md +83 -0
  32. package/agent-spine-plugin/docs/roadmap.md +307 -0
  33. package/agent-spine-plugin/docs/selfstarter.md +88 -0
  34. package/agent-spine-plugin/docs/session-briefing.md +74 -0
  35. package/agent-spine-plugin/docs/shared-memory.md +259 -0
  36. package/agent-spine-plugin/docs/source-roots.md +86 -0
  37. package/agent-spine-plugin/docs/sqlite-transport.md +76 -0
  38. package/agent-spine-plugin/hooks/hooks.json +95 -0
  39. package/agent-spine-plugin/hooks/version.json +5 -0
  40. package/agent-spine-plugin/package.json +69 -0
  41. package/agent-spine-plugin/scripts/check-hosts.js +193 -0
  42. package/agent-spine-plugin/scripts/check-install.js +551 -0
  43. package/agent-spine-plugin/scripts/check-syntax.js +29 -0
  44. package/agent-spine-plugin/scripts/github-actions.js +11 -0
  45. package/agent-spine-plugin/scripts/release-check.js +127 -0
  46. package/agent-spine-plugin/scripts/run-acceptance.js +19 -0
  47. package/agent-spine-plugin/scripts/run-checks.js +46 -0
  48. package/agent-spine-plugin/scripts/run-tests-hermetic.js +73 -0
  49. package/agent-spine-plugin/skill/SKILL.md +76 -0
  50. package/agent-spine-plugin/skills/agent-spine/SKILL.md +84 -0
  51. package/agent-spine-plugin/spine-example/1-identity.md +12 -0
  52. package/agent-spine-plugin/spine-example/2-voice.md +6 -0
  53. package/agent-spine-plugin/spine-example/3-conduct.md +8 -0
  54. package/agent-spine-plugin/spine-example/4-history.md +4 -0
  55. package/agent-spine-plugin/src/cli.js +950 -0
  56. package/agent-spine-plugin/src/hook.js +646 -0
  57. package/agent-spine-plugin/src/index.js +84 -0
  58. package/agent-spine-plugin/src/lib/acceptance.js +294 -0
  59. package/agent-spine-plugin/src/lib/attention.js +755 -0
  60. package/agent-spine-plugin/src/lib/audit.js +308 -0
  61. package/agent-spine-plugin/src/lib/authentication.js +513 -0
  62. package/agent-spine-plugin/src/lib/briefing.js +305 -0
  63. package/agent-spine-plugin/src/lib/catalog.js +142 -0
  64. package/agent-spine-plugin/src/lib/channel-runtime.js +665 -0
  65. package/agent-spine-plugin/src/lib/context.js +154 -0
  66. package/agent-spine-plugin/src/lib/continuity.js +333 -0
  67. package/agent-spine-plugin/src/lib/coordination.js +577 -0
  68. package/agent-spine-plugin/src/lib/documents.js +199 -0
  69. package/agent-spine-plugin/src/lib/feed-transport.js +497 -0
  70. package/agent-spine-plugin/src/lib/filesystem-retry.js +27 -0
  71. package/agent-spine-plugin/src/lib/gateway-runtime.js +760 -0
  72. package/agent-spine-plugin/src/lib/graph.js +284 -0
  73. package/agent-spine-plugin/src/lib/https-transport.js +392 -0
  74. package/agent-spine-plugin/src/lib/indexed-memory-offline.js +40 -0
  75. package/agent-spine-plugin/src/lib/indexed-memory.js +281 -0
  76. package/agent-spine-plugin/src/lib/learning.js +645 -0
  77. package/agent-spine-plugin/src/lib/object-transport.js +206 -0
  78. package/agent-spine-plugin/src/lib/paths.js +60 -0
  79. package/agent-spine-plugin/src/lib/peer-transport.js +283 -0
  80. package/agent-spine-plugin/src/lib/persona-runtime.js +503 -0
  81. package/agent-spine-plugin/src/lib/runtime.js +13 -0
  82. package/agent-spine-plugin/src/lib/selfstarter.js +819 -0
  83. package/agent-spine-plugin/src/lib/sharing.js +969 -0
  84. package/agent-spine-plugin/src/lib/source-roots.js +451 -0
  85. package/agent-spine-plugin/src/lib/sqlite-transport.js +501 -0
  86. package/agent-spine-plugin/src/lib/telegram-adapter.js +119 -0
  87. package/agent-spine-plugin/src/lib/voice-runtime.js +39 -0
  88. package/agent-spine-plugin/src/mcp.js +526 -0
  89. package/agent-spine-plugin/src/version.js +1 -0
  90. package/agent-spine-plugin/src/worker.js +178 -0
  91. package/bin/identity-context-policy.cjs +51 -1
  92. package/bin/launcher-runtime.js +22 -1
  93. package/bin/plugin-bootstrap.js +68 -27
  94. package/bin/startup-preferences.cjs +130 -0
  95. package/bin/turn-thinking-policy.cjs +5 -4
  96. package/bin/turn-tool-performance-policy.cjs +15 -2
  97. package/bin/update-notice.js +104 -43
  98. package/blun.mjs +108 -32
  99. package/package.json +2 -1
@@ -17,6 +17,12 @@ const TOOL_SEARCH_INTENT_WORDS = new Set([
17
17
  'find', 'fetch', 'get', 'holen', 'list', 'read', 'search', 'show', 'anzeigen', 'lesen', 'suchen',
18
18
  ]);
19
19
  const TOOL_SEARCH_RELATED_TERM_GROUPS = Object.freeze([
20
+ Object.freeze([
21
+ 'checklist', 'list', 'liste', 'listen',
22
+ ]),
23
+ Object.freeze([
24
+ 'aufgabe', 'aufgaben', 'aufgabenliste', 'todo', 'todos',
25
+ ]),
20
26
  Object.freeze([
21
27
  'current', 'inbox', 'latest', 'message', 'messages', 'nachricht', 'nachrichten', 'queue', 'queued',
22
28
  'recent', 'letzte', 'letzten', 'letzter', 'vergangen', 'update', 'updates',
@@ -195,7 +201,10 @@ function rankingTokens(value) {
195
201
  function toolRankingDocument(tool) {
196
202
  const name = String(tool?.name || '');
197
203
  const leaf = name.split(/__|:/).at(-1) || name;
198
- const nameTokens = rankingTokens(`${name.replaceAll('_', ' ')} ${leaf.replaceAll('_', ' ')}`);
204
+ const splitToolName = (value) => String(value || '')
205
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
206
+ .replaceAll('_', ' ');
207
+ const nameTokens = rankingTokens(`${splitToolName(name)} ${splitToolName(leaf)}`);
199
208
  const descriptionTokens = rankingTokens(tool?.description);
200
209
  const parameterText = [];
201
210
  const properties = tool?.parameters?.properties;
@@ -247,14 +256,18 @@ function rankedToolNamesForTurnText(tools, value, options = {}) {
247
256
  let score = 0;
248
257
  let matchedTokens = 0;
249
258
  let exactNameMatches = 0;
259
+ let relatedNameMatches = 0;
250
260
  for (const token of queryTokens) {
251
261
  const tokenScore = tokenMatchScore(document, token);
252
262
  if (tokenScore === 0) continue;
253
263
  score += tokenScore;
254
264
  matchedTokens += 1;
255
265
  if (document.nameTokens.has(token)) exactNameMatches += 1;
266
+ else if (relatedSearchTerms(token).some((term) => document.nameTokens.has(term))) relatedNameMatches += 1;
256
267
  }
257
- const highConfidence = matchedTokens >= 2 || (exactNameMatches >= 1 && score >= 10);
268
+ const highConfidence = matchedTokens >= 2
269
+ || (exactNameMatches >= 1 && score >= 10)
270
+ || (relatedNameMatches >= 1 && score >= 5);
258
271
  return highConfidence ? { name: document.name, score, matchedTokens, exactNameMatches } : null;
259
272
  }).filter(Boolean).sort((left, right) => (
260
273
  right.matchedTokens - left.matchedTokens
@@ -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({ currentVersion, release, input, output, processRef = process }) {
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: `Jetzt aktualisieren (führt \`${installCommandText(release.version)}\` aus)`,
721
+ label: copy.install(release.version),
666
722
  },
667
- { choice: 'skip-once', label: 'Überspringen' },
668
- { choice: 'skip-version', label: 'Auf den nächsten Release warten' },
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}Enter drücken, um fortzufahren${reset}\n`);
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(`\nBLUN Code-Update verfügbar: ${currentVersion} -> ${release.version}\n`);
889
+ output.write(`\n${copy.available(currentVersion, release.version)}\n`);
834
890
  if (release.notesUrl) {
835
- output.write(`${dim}Versionshinweise:${reset} ${underline}${release.notesUrl}${reset}\n`);
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
- ? `Kein Update verfügbar. Installiert: ${currentVersion} · Aktuell: ${currentVersion}.\n`
1296
- : `Kein sicherer Update-Zielstand verfügbar. Installiert: ${currentVersion}.\n`);
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(`Update fehlgeschlagen (Code ${exitCode}).\n`);
1361
+ stderr.write(`${copy.failed(exitCode)}\n`);
1304
1362
  } else {
1305
- stderr.write('Das Update konnte nicht verifiziert werden.\n');
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, 'Update geprüft');
1480
- updateProgress(2, 'Installer bereit');
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, 'Paket wird installiert');
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, 'Installation geprüft');
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
- ? `Update ${currentVersion} -> ${release.version} erfolgreich installiert. Die letzte Sitzung wird mit der neuen Version fortgesetzt.\n`
1528
- : `Update ${currentVersion} -> ${release.version} erfolgreich installiert. Starte BLUN Code neu, um die neue Version zu verwenden.\n`);
1529
- if (release.notesUrl) stdout.write(`Versionshinweise: ${release.notesUrl}\n`);
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(`Update fehlgeschlagen (Code ${installResult.code}). Die vorhandene Version wird gestartet.\n`);
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('Update konnte nicht verifiziert werden. Starte BLUN Code neu.\n');
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) {