blun-king-cli 9.1.624 → 9.1.626

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 (142) hide show
  1. package/CHANGELOG.md +62 -213
  2. package/LIESMICH.txt +57 -74
  3. package/README.md +76 -119
  4. package/agent-spine-plugin/scripts/check-install.js +4 -4
  5. package/agent-spine-plugin/src/hook.js +0 -4
  6. package/agent-spine-plugin/src/lib/documents.js +1 -1
  7. package/agent-spine-plugin/src/lib/hook-context.js +0 -1
  8. package/agent-spine-plugin/src/lib/host-instruction-budget.js +2 -1
  9. package/agent-spine-plugin/src/lib/preflight.js +9 -38
  10. package/agent-spine-plugin/src/lib/source-roots.js +1 -1
  11. package/bin/agentspine-king-goal-inbox.mjs +127 -127
  12. package/bin/agentspine-king-goal-intake.mjs +106 -106
  13. package/bin/agentspine-king-host-runner.mjs +109 -109
  14. package/bin/agentspine-king-snapshot-policy.cjs +80 -80
  15. package/bin/agentspine-king-status-policy.mjs +226 -226
  16. package/bin/agentspine-king-worker-host.mjs +160 -160
  17. package/bin/core-bootstrap.js +83 -97
  18. package/bin/launcher-mode.js +93 -93
  19. package/bin/launcher-restart-policy.cjs +131 -131
  20. package/bin/launcher-runtime.js +91 -254
  21. package/bin/managed-node.js +186 -186
  22. package/bin/managed-plugin-selection.cjs +109 -116
  23. package/bin/native-module-repair.js +201 -201
  24. package/bin/node-runtime.js +34 -34
  25. package/bin/node-version.js +49 -49
  26. package/bin/plugin-bootstrap.js +149 -172
  27. package/bin/private-paths.js +1578 -1624
  28. package/bin/runtime-exit-ledger.cjs +144 -144
  29. package/bin/runtime-exit-ledger.d.cts +23 -23
  30. package/bin/standard-tools-bootstrap.js +277 -272
  31. package/bin/turn-thinking-policy.cjs +82 -82
  32. package/bin/update-copy.js +200 -200
  33. package/bin/update-lease.js +597 -599
  34. package/bin/update-notice.js +1568 -1568
  35. package/bin/verify-agent-behavior.cjs +122 -122
  36. package/bin/verify-agent-components.cjs +104 -104
  37. package/bin/verify-bundled-agent-sources.cjs +91 -96
  38. package/bin/windows-node-crash-dump.cjs +289 -289
  39. package/blun.mjs +187640 -180475
  40. package/bundled-agent-sources.json +26 -30
  41. package/codebase-index/codebase_index.py +462 -470
  42. package/dist-web/assets/{CodeBlockNode-TKKkJX8L.js → CodeBlockNode-BMbuG85x.js} +1 -1
  43. package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-CUj2Ds5x.js → CodeBlockShell.vue_vue_type_style_index_0_lang-C1fv7l_Z.js} +1 -1
  44. package/dist-web/assets/DesignSystemView-6HgAUEmC.css +1 -0
  45. package/dist-web/assets/DesignSystemView-CEEBqXSX.js +12 -0
  46. package/dist-web/assets/{Tooltip-CTWv7WCU.js → Tooltip--YoauJ24.js} +1 -1
  47. package/dist-web/assets/{abnfDiagram-N423BO3Z-DA8V8Zjh.js → abnfDiagram-N423BO3Z-DZvBWkRg.js} +1 -1
  48. package/dist-web/assets/{arc-YtddKbdY.js → arc-B04JATeX.js} +1 -1
  49. package/dist-web/assets/{architectureDiagram-T3A2C74G-CGEiObmo.js → architectureDiagram-T3A2C74G-DmYnMep2.js} +1 -1
  50. package/dist-web/assets/{blockDiagram-VBNYF7ZC-Bd5Vt50e.js → blockDiagram-VBNYF7ZC-DJ1gPS1C.js} +1 -1
  51. package/dist-web/assets/{c4Diagram-5PPSVZJV-D2ApPM54.js → c4Diagram-5PPSVZJV-DmjxvUbd.js} +1 -1
  52. package/dist-web/assets/channel-472fcEvw.js +1 -0
  53. package/dist-web/assets/{chunk-2GRJ4B5K-BDcIEZSl.js → chunk-2GRJ4B5K-AB0raj3I.js} +1 -1
  54. package/dist-web/assets/{chunk-2Q5K7J3B-6aSabCX7.js → chunk-2Q5K7J3B-Drf039vM.js} +1 -1
  55. package/dist-web/assets/{chunk-5RXB4S5H-BFRQvIJS.js → chunk-5RXB4S5H-D5ILttmz.js} +1 -1
  56. package/dist-web/assets/{chunk-5VM5RSS4-ChAa-DNY.js → chunk-5VM5RSS4-DrLSdi8y.js} +1 -1
  57. package/dist-web/assets/{chunk-6Q2QTUOP-BIfrb2Jc.js → chunk-6Q2QTUOP-LiaqdEOQ.js} +1 -1
  58. package/dist-web/assets/{chunk-GF5L2VYU-BR0gvtWI.js → chunk-GF5L2VYU-AIYkb--o.js} +1 -1
  59. package/dist-web/assets/{chunk-JWPE2WC7-BgXKsx5E.js → chunk-JWPE2WC7-CogdNl0i.js} +1 -1
  60. package/dist-web/assets/{chunk-KBJHAD2P-I8mrZhpz.js → chunk-KBJHAD2P-DHjpNtZv.js} +1 -1
  61. package/dist-web/assets/{chunk-RYQCIY6F-BMPaem92.js → chunk-RYQCIY6F-BUSOqH2X.js} +1 -1
  62. package/dist-web/assets/{chunk-XXDRQBXY-COy0J-0j.js → chunk-XXDRQBXY-BpoMV0bh.js} +1 -1
  63. package/dist-web/assets/classDiagram-JCYQIIEL-BTZeLngj.js +1 -0
  64. package/dist-web/assets/classDiagram-v2-OCEON4UE-BTZeLngj.js +1 -0
  65. package/dist-web/assets/{cose-bilkent-JH36ORCC-MosTTRdo.js → cose-bilkent-JH36ORCC-BJr2I61o.js} +1 -1
  66. package/dist-web/assets/{cynefin-VYW2F7L2-5tjPgrkP.js → cynefin-VYW2F7L2-HtysQZ4A.js} +1 -1
  67. package/dist-web/assets/{cynefinDiagram-MW4NZA55-CbDcdInR.js → cynefinDiagram-MW4NZA55-CcpC_2uv.js} +1 -1
  68. package/dist-web/assets/{dagre-VZM6K2ZE-YaBom1ZH.js → dagre-VZM6K2ZE-D8Ao0LUg.js} +1 -1
  69. package/dist-web/assets/{diagram-7IWD3JNH-Da4m-Hgz.js → diagram-7IWD3JNH-BITiLhjX.js} +1 -1
  70. package/dist-web/assets/{diagram-B4RE2ZJO-CAUUegxg.js → diagram-B4RE2ZJO-CJtwfy9f.js} +1 -1
  71. package/dist-web/assets/{diagram-LBJQPF4R-o21mWKG4.js → diagram-LBJQPF4R-BsVTh6w8.js} +1 -1
  72. package/dist-web/assets/{diagram-Q27KOJAE-BA3z3sXf.js → diagram-Q27KOJAE-pA_MUCUf.js} +1 -1
  73. package/dist-web/assets/{diagram-UB23O5K3-CGRdSSDK.js → diagram-UB23O5K3-CIY8z7vu.js} +1 -1
  74. package/dist-web/assets/{ebnfDiagram-BXEA7PRR-Bw-iU9FP.js → ebnfDiagram-BXEA7PRR-C3FMioqp.js} +1 -1
  75. package/dist-web/assets/{erDiagram-JOGREHBK-BwM1yiR0.js → erDiagram-JOGREHBK-CzoyKmKc.js} +1 -1
  76. package/dist-web/assets/{flowDiagram-UKHOOZJN-z05eOR1Q.js → flowDiagram-UKHOOZJN-DOqfushy.js} +1 -1
  77. package/dist-web/assets/{ganttDiagram-PKOTCBZU-BMUubNTl.js → ganttDiagram-PKOTCBZU-Cf9XQSWl.js} +1 -1
  78. package/dist-web/assets/{gitGraphDiagram-DS77QQ5N-Dccbi1wU.js → gitGraphDiagram-DS77QQ5N-DHUDofE5.js} +1 -1
  79. package/dist-web/assets/{index-h0KEOmkU.js → index-B6qEMQMx.js} +14 -14
  80. package/dist-web/assets/{index-C9eDH3u-.css → index-BmKj7CB1.css} +1 -1
  81. package/dist-web/assets/{index-BBbC5LRF.js → index-DokxDX1w.js} +1 -1
  82. package/dist-web/assets/{index-D48p0M2S.js → index-auojtiAA.js} +2 -2
  83. package/dist-web/assets/{index10-Qbuw1N6u.js → index10-Drb2n5e5.js} +1 -1
  84. package/dist-web/assets/{index11-g8v025wN.js → index11-Cx-aV4G2.js} +1 -1
  85. package/dist-web/assets/{index5-BYNcV8BY.js → index5-Dg3qGTyH.js} +1 -1
  86. package/dist-web/assets/{index6-BetANtnV.js → index6-BgvtIICP.js} +1 -1
  87. package/dist-web/assets/{index7-BcPbgCKN.js → index7-uEnniPQG.js} +1 -1
  88. package/dist-web/assets/{index8-B1lp-RvF.js → index8-h4IKc0ek.js} +2 -2
  89. package/dist-web/assets/{infoDiagram-6WML65LV-BF_pbUnN.js → infoDiagram-6WML65LV-D-3tvEiJ.js} +1 -1
  90. package/dist-web/assets/{ishikawaDiagram-WSZJBQD7-Dedv4urS.js → ishikawaDiagram-WSZJBQD7-DIIBNv7a.js} +1 -1
  91. package/dist-web/assets/{journeyDiagram-NVQOT4AX-B1Ex3b6o.js → journeyDiagram-NVQOT4AX-DP4r1Vlx.js} +1 -1
  92. package/dist-web/assets/{kanban-definition-27J2QSJJ-BtCGliBH.js → kanban-definition-27J2QSJJ-C3_Ztgxv.js} +1 -1
  93. package/dist-web/assets/{linear-ByItc8Qr.js → linear-DnqhIw-y.js} +1 -1
  94. package/dist-web/assets/{mermaid.core-B1M2O7nN.js → mermaid.core-xYUgBa3T.js} +4 -4
  95. package/dist-web/assets/{mindmap-definition-FAOFIHXS-D0UHKUyj.js → mindmap-definition-FAOFIHXS-l-dq-zfr.js} +1 -1
  96. package/dist-web/assets/{pegDiagram-VL7TDLO6-D7zYCVmG.js → pegDiagram-VL7TDLO6-C8vXQiaJ.js} +1 -1
  97. package/dist-web/assets/{pieDiagram-7S7Q4E2Y-Bd0i9CHa.js → pieDiagram-7S7Q4E2Y-CyNRSsI6.js} +1 -1
  98. package/dist-web/assets/{quadrantDiagram-CIZ2JOQS-MG-Ug47d.js → quadrantDiagram-CIZ2JOQS-D-w8AD_g.js} +1 -1
  99. package/dist-web/assets/{railroadDiagram-AXF67PYL-AZdl90Gj.js → railroadDiagram-AXF67PYL-BLkyQCWy.js} +1 -1
  100. package/dist-web/assets/{requirementDiagram-LRYGKXZP-DjplF9kt.js → requirementDiagram-LRYGKXZP-CEWO7XfT.js} +1 -1
  101. package/dist-web/assets/{sankeyDiagram-W5VNT64P-Bi9Zgfjs.js → sankeyDiagram-W5VNT64P-ByGoAaGj.js} +1 -1
  102. package/dist-web/assets/{sequenceDiagram-SI44F4Z6-ChEpdCvb.js → sequenceDiagram-SI44F4Z6-Bhn9GQtd.js} +1 -1
  103. package/dist-web/assets/{sizeCapture-X5ZJPWSS-B5RFUdaa.js → sizeCapture-X5ZJPWSS-jVKR9CTu.js} +1 -1
  104. package/dist-web/assets/{stateDiagram-OKZ733FA-BkRblSKp.js → stateDiagram-OKZ733FA-wW3XbegA.js} +1 -1
  105. package/dist-web/assets/stateDiagram-v2-UEYNNEHI-B8aids-Z.js +1 -0
  106. package/dist-web/assets/{swimlanes-SLNWSIFB-DLXH6Zhc.js → swimlanes-SLNWSIFB-B8QyFS7G.js} +2 -2
  107. package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-B8XAkdSm.js +8 -0
  108. package/dist-web/assets/{timeline-definition-Z64GVDOM-C_N88siO.js → timeline-definition-Z64GVDOM-DpvxS-1A.js} +1 -1
  109. package/dist-web/assets/{vennDiagram-T6HMQDX7-DMsnvDt0.js → vennDiagram-T6HMQDX7-BzGM0ihY.js} +1 -1
  110. package/dist-web/assets/{vue.runtime.esm-bundler-B-3uIy85.js → vue.runtime.esm-bundler-BOcpwIX1.js} +1 -1
  111. package/dist-web/assets/{wardleyDiagram-T6FBY63Y-C9SJIPzq.js → wardleyDiagram-T6FBY63Y-2DKAOs5e.js} +1 -1
  112. package/dist-web/assets/{xychartDiagram-ELKLHX3M-DZLWA6Go.js → xychartDiagram-ELKLHX3M-B0SP0TXd.js} +1 -1
  113. package/dist-web/index.html +32 -32
  114. package/dist-web/vis/index.html.gz +0 -0
  115. package/package.json +1 -1
  116. package/scripts/fix-node-pty-perms.js +53 -53
  117. package/standard-skills/blun-app-design-system/SKILL.md +30 -30
  118. package/standard-skills/blun-app-design-system/provenance.json +17 -17
  119. package/standard-skills/blun-app-design-system/references/tokens.md +48 -48
  120. package/standard-skills/blun-app-design-system/scripts/check-blun-design.mjs +49 -49
  121. package/standard-skills/translate-native/README.md +1 -1
  122. package/standard-skills/translate-native/scripts/blun_language_guard.py +2 -0
  123. package/standard-skills/translate-native/scripts/language_gateway.py +2 -0
  124. package/standard-skills/translate-native/scripts/pre_output_guard.py +2 -0
  125. package/standard-tools/language-guard/blun_language_guard.py +2 -0
  126. package/standard-tools/language-guard/language_gateway.py +2 -0
  127. package/standard-tools/language-guard/pre_output_guard.py +2 -0
  128. package/telegram-plugin/blun.plugin.json +20 -20
  129. package/telegram-plugin/commands/access.md +37 -37
  130. package/telegram-plugin/dist/bridge.mjs +310 -187
  131. package/telegram-plugin/dist/mcp-server.mjs +174 -261
  132. package/telegram-plugin/dist/noise.mjs +1 -19
  133. package/worker-host.mjs +13747 -16824
  134. package/bin/profile-handoff.cjs +0 -152
  135. package/bin/profile-launch.cjs +0 -120
  136. package/dist-web/assets/DesignSystemView-DwK1aQMo.js +0 -12
  137. package/dist-web/assets/DesignSystemView-szjTj7ns.css +0 -1
  138. package/dist-web/assets/channel-BnluexuN.js +0 -1
  139. package/dist-web/assets/classDiagram-JCYQIIEL-BliFdSD9.js +0 -1
  140. package/dist-web/assets/classDiagram-v2-OCEON4UE-BliFdSD9.js +0 -1
  141. package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fVkQcACW.js +0 -1
  142. package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-Bg-BiZJQ.js +0 -8
@@ -33,69 +33,28 @@ const { unsupportedNodeMessage } = require('./node-version');
33
33
  const { repairConfiguredNativeModules } = require('./native-module-repair');
34
34
  const { acquireSharedRuntimeLease, tryAcquireUpdateLease } = require('./update-lease');
35
35
  const { runExplicitUpdate, runUpdateNotice } = require('./update-notice');
36
- const {
37
- ensurePrivateDirectory,
38
- securePrivateFile,
39
- writePrivateFile,
40
- } = require('./private-paths');
41
- const { parseProfileLaunchArgs, resolveSelectedProfile } = require('./profile-launch.cjs');
42
- const { createProfileHandoff, PROFILE_HANDOFF_READY, PROFILE_HANDOFF_EXIT } = require('./profile-handoff.cjs');
43
-
44
- const PKG = path.resolve(__dirname, '..');
45
- const PROFILE = parseProfileLaunchArgs(process.argv.slice(2), launcherModeFromArgv(process.argv));
46
- const ARGS = PROFILE.args;
47
- const CORE_LOAD_TIMEOUT_MS = 30_000;
36
+ const {
37
+ ensurePrivateDirectory,
38
+ securePrivateFile,
39
+ writePrivateFile,
40
+ } = require('./private-paths');
41
+
42
+ const PKG = path.resolve(__dirname, '..');
43
+ const ARGS = process.argv.slice(2);
48
44
 
49
- function normalizeWindowsPath(value) {
50
- return path.win32.normalize(value).replace(/\\+$/u, '').toLowerCase();
51
- }
52
-
53
- function runningTuiPid(blunDir, options = {}) {
54
- const fsImpl = options.fsImpl || fs;
55
- const kill = options.kill || process.kill.bind(process);
56
- const now = options.now ?? Date.now();
57
- const stateDir = path.join(blunDir, 'channels', 'telegram');
58
- try {
59
- const leaseFile = path.join(stateDir, 'tui.pid');
60
- const owner = JSON.parse(fsImpl.readFileSync(path.join(stateDir, 'tui-owner.json'), 'utf8'));
61
- const leasePid = Number(fsImpl.readFileSync(leaseFile, 'utf8').trim());
62
- if (owner?.version !== 1 || !Number.isSafeInteger(owner.pid) || owner.pid <= 1
63
- || owner.pid !== leasePid || now - fsImpl.statSync(leaseFile).mtimeMs > 90_000) return null;
64
- kill(owner.pid, 0);
65
- return owner.pid;
66
- } catch {
67
- return null;
68
- }
69
- }
70
-
71
- function isInteractiveKingStart(args) {
72
- return args.length === 0 || (args.length === 1 && args[0] === '-c');
73
- }
45
+ function normalizeWindowsPath(value) {
46
+ return path.win32.normalize(value).replace(/\\+$/u, '').toLowerCase();
47
+ }
74
48
 
75
- function resolveLauncherPrivatePaths(options = {}) {
76
- const env = options.env || process.env;
77
- const platform = options.platform || process.platform;
78
- const configuredHome = String(env.BLUN_HOME || '').trim();
79
- const selectedProfile = options.profileName ?? PROFILE.name;
80
- if (platform !== 'win32') {
81
- const posix = path.posix;
82
- const userHome = (options.homedir || os.homedir)();
83
- if (selectedProfile !== undefined) {
84
- const configuredShared = String(env.BLUN_SHARED_HOME || '').trim();
85
- const sharedHome = configuredShared
86
- ? posix.resolve(configuredShared)
87
- : configuredHome && posix.basename(posix.dirname(configuredHome)) === 'profile'
88
- ? posix.resolve(configuredHome, '..', '..')
89
- : configuredHome ? posix.resolve(configuredHome) : posix.join(userHome, '.blun');
90
- const blunHome = resolveSelectedProfile(sharedHome, selectedProfile, posix);
91
- if (configuredShared && configuredHome && posix.resolve(configuredHome) !== blunHome) {
92
- throw new Error(`BLUN_HOME passt nicht zum Profil ${selectedProfile}: ${blunHome}`);
93
- }
94
- return { blunHome, sharedHome, userHome };
95
- }
96
- return {
97
- blunHome: configuredHome ? path.resolve(configuredHome) : path.join(userHome, '.blun'),
98
- userHome,
49
+ function resolveLauncherPrivatePaths(options = {}) {
50
+ const env = options.env || process.env;
51
+ const platform = options.platform || process.platform;
52
+ const configuredHome = String(env.BLUN_HOME || '').trim();
53
+ if (platform !== 'win32') {
54
+ const userHome = (options.homedir || os.homedir)();
55
+ return {
56
+ blunHome: configuredHome ? path.resolve(configuredHome) : path.join(userHome, '.blun'),
57
+ userHome,
99
58
  };
100
59
  }
101
60
 
@@ -118,20 +77,8 @@ function resolveLauncherPrivatePaths(options = {}) {
118
77
  throw new Error('Das lokale Windows-Benutzerprofil ist kein kanonischer lokaler Pfad.');
119
78
  }
120
79
 
121
- const blunHome = path.win32.join(userHome, '.blun');
122
- if (selectedProfile !== undefined) {
123
- const profileHome = resolveSelectedProfile(blunHome, selectedProfile, path.win32);
124
- const configuredShared = String(env.BLUN_SHARED_HOME || '').trim();
125
- if (configuredShared && normalizeWindowsPath(path.win32.resolve(configuredShared)) !== normalizeWindowsPath(blunHome)) {
126
- throw new Error(`BLUN_SHARED_HOME muss unter Windows exakt im Windows-Benutzerprofil liegen: ${blunHome}`);
127
- }
128
- if (configuredHome && normalizeWindowsPath(path.win32.resolve(configuredHome)) !== normalizeWindowsPath(profileHome)
129
- && normalizeWindowsPath(path.win32.resolve(configuredHome)) !== normalizeWindowsPath(blunHome)) {
130
- throw new Error(`BLUN_HOME passt nicht zum Profil ${selectedProfile}: ${profileHome}`);
131
- }
132
- return { blunHome: profileHome, sharedHome: blunHome, userHome };
133
- }
134
- if (configuredHome
80
+ const blunHome = path.win32.join(userHome, '.blun');
81
+ if (configuredHome
135
82
  && normalizeWindowsPath(path.win32.resolve(configuredHome)) !== normalizeWindowsPath(blunHome)) {
136
83
  throw new Error(`BLUN_HOME muss unter Windows exakt im Windows-Benutzerprofil liegen: ${blunHome}`);
137
84
  }
@@ -148,42 +95,35 @@ function readPackageVersion() {
148
95
 
149
96
  function shouldDetachProtectedCore(options = {}) {
150
97
  const platform = options.platform || process.platform;
151
- if (platform === 'win32' && options.interactive === true) return false;
152
98
  const stdinIsTTY = Object.hasOwn(options, 'stdinIsTTY')
153
99
  ? options.stdinIsTTY
154
100
  : process.stdin.isTTY;
155
101
  return platform !== 'win32' || stdinIsTTY !== true;
156
102
  }
157
103
 
158
- function spawnProtectedCore(args, env, cwd, onProfileMessage) {
104
+ function spawnProtectedCore(args, env, cwd) {
105
+ const terminalOwner = process.platform === 'win32' && process.stdin.isTTY === true;
159
106
  const child = spawn(
160
107
  process.execPath,
161
108
  [path.join(PKG, 'bin', 'core-bootstrap.js'), ...args],
162
109
  {
163
110
  cwd,
164
- detached: shouldDetachProtectedCore({ interactive: Boolean(onProfileMessage) }),
165
- env: { ...env, BLUN_TERMINAL_OWNER: process.platform === 'win32' && onProfileMessage ? '1' : '0' },
111
+ detached: shouldDetachProtectedCore(),
112
+ env: { ...env, BLUN_TERMINAL_OWNER: terminalOwner ? '1' : '0' },
166
113
  stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
167
114
  windowsHide: true,
168
115
  },
169
116
  );
170
117
  let loadedSettled = false;
171
118
  let completedSettled = false;
172
- let operatorSignal;
173
- let profileReady = false;
119
+ let operatorSignal;
174
120
  let resolveLoaded;
175
121
  let resolveCompleted;
176
- const loadTimer = setTimeout(() => {
177
- try {
178
- child.kill();
179
- } catch {}
180
- }, CORE_LOAD_TIMEOUT_MS);
181
122
  const loaded = new Promise((resolve) => { resolveLoaded = resolve; });
182
123
  const completed = new Promise((resolve) => { resolveCompleted = resolve; });
183
124
  const settleLoaded = (value) => {
184
125
  if (loadedSettled) return;
185
126
  loadedSettled = true;
186
- clearTimeout(loadTimer);
187
127
  resolveLoaded(value);
188
128
  };
189
129
  const settleCompleted = (result) => {
@@ -204,29 +144,17 @@ function spawnProtectedCore(args, env, cwd, onProfileMessage) {
204
144
  signalHandlers.set(signal, handler);
205
145
  process.once(signal, handler);
206
146
  }
207
- child.on('message', (message) => {
208
- if (message?.type !== CORE_LOADED_MESSAGE) {
209
- if (completedSettled || !onProfileMessage) return;
210
- if (message?.type === PROFILE_HANDOFF_READY && Object.keys(message).length === 1) {
211
- profileReady = true;
212
- return;
213
- }
214
- if (!loadedSettled) return;
215
- const reply = onProfileMessage(message);
216
- if (reply) {
217
- try { child.send(reply, () => {}); } catch {}
218
- }
219
- return;
220
- }
221
- settleLoaded(true);
222
- if (onProfileMessage) child.channel?.unref();
223
- else {
224
- try { child.disconnect(); } catch {}
225
- }
147
+ child.on('message', (message) => {
148
+ if (message?.type !== CORE_LOADED_MESSAGE) return;
149
+ settleLoaded(true);
150
+ if (terminalOwner) return;
151
+ try {
152
+ child.disconnect();
153
+ } catch {}
226
154
  });
227
155
  child.once('error', (error) => settleCompleted({ error }));
228
156
  child.once('exit', (code, signal) => settleCompleted({ code, signal }));
229
- return { child, completed, loaded, isProfileReady: () => profileReady };
157
+ return { child, completed, loaded };
230
158
  }
231
159
 
232
160
  async function runInformationalCore(args, env, cwd, releaseNotice) {
@@ -238,14 +166,10 @@ async function runInformationalCore(args, env, cwd, releaseNotice) {
238
166
  return Number.isInteger(result.code) ? result.code : exitCodeForChild(result, false);
239
167
  }
240
168
 
241
- async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {}) {
242
- let noticeReleased = false;
243
- let rollback;
244
- let recoveryAttempted = false;
245
- for (;;) {
246
- const handoff = options.prepareProfile
247
- ? createProfileHandoff(env, target => runningTuiPid(target) !== null) : undefined;
248
- const core = spawnProtectedCore(args, env, cwd, handoff && ((message) => handoff.prepare(message)));
169
+ async function superviseProtectedCore(args, env, cwd, releaseNotice) {
170
+ let noticeReleased = false;
171
+ for (;;) {
172
+ const core = spawnProtectedCore(args, env, cwd);
249
173
  const loaded = await core.loaded;
250
174
  if (!noticeReleased) {
251
175
  noticeReleased = true;
@@ -256,47 +180,12 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
256
180
  const intentionalStop = consumeIntentionalStopMarker({
257
181
  homeDir: env.BLUN_HOME, childPid: core.child.pid, nowMs: Date.now(),
258
182
  });
259
- recordRuntimeExit({
183
+ recordRuntimeExit({
260
184
  homeDir: env.BLUN_HOME, source: 'launcher', kind: result.error ? 'child-error' : 'child-exit',
261
185
  exitCode, signal: result.signal, phase: loaded ? 'runtime' : 'startup',
262
186
  cliVersion: env.BLUN_PUBLIC_PACKAGE_VERSION, profile: env.BLUN_PROFILE,
263
- loaded, childPid: core.child.pid, error: result.error,
264
- });
265
- // A profile transition is committed only after the old process exits cleanly.
266
- // Failed target startup restores the previous owner, never the previous PID.
267
- if (rollback && (!loaded || !core.isProfileReady()) && !result.signal) {
268
- ({ args, env } = rollback);
269
- rollback = undefined;
270
- continue;
271
- }
272
- if (loaded && core.isProfileReady()) {
273
- rollback = undefined;
274
- recoveryAttempted = false;
275
- }
276
- if (handoff && loaded && !intentionalStop && !result.error && !result.signal
277
- && result.code === PROFILE_HANDOFF_EXIT) {
278
- if (!handoff.hasPending()) return 1;
279
- const sourceSessionId = handoff.getSourceSessionId();
280
- const recoveryArgs = sourceSessionId === undefined ? ['-c'] : ['-r', sourceSessionId];
281
- try {
282
- const selected = handoff.commit();
283
- const nextEnv = await options.prepareProfile(selected);
284
- handoff.commit();
285
- rollback = { args: recoveryArgs, env };
286
- args = ['-c'];
287
- env = { ...nextEnv, BLUN_PROFILE_HANDOFF: '1' };
288
- continue;
289
- } catch (error) {
290
- recordRuntimeExit({ homeDir: env.BLUN_HOME, source: 'launcher', kind: 'profile-handoff-failure',
291
- phase: 'startup', cliVersion: env.BLUN_PUBLIC_PACKAGE_VERSION, profile: env.BLUN_PROFILE,
292
- exitCode: 1, error });
293
- if (recoveryAttempted) return 1;
294
- recoveryAttempted = true;
295
- // Reopen the original owner when the selection became unavailable.
296
- args = recoveryArgs;
297
- continue;
298
- }
299
- }
187
+ loaded, childPid: core.child.pid, error: result.error,
188
+ });
300
189
  if (intentionalStop || !isAbnormalCoreExit(result, loaded)) {
301
190
  if (result.error) throw result.error;
302
191
  return exitCode;
@@ -327,7 +216,7 @@ function exitCodeForChild(result, loaded) {
327
216
  return 1;
328
217
  }
329
218
 
330
- function installTelegramForProfile(packageRoot, blunDir) {
219
+ function installTelegramForProfile(packageRoot, blunDir) {
331
220
  installManagedTelegramPlugin({ packageRoot, blunDir });
332
221
  const channelsDir = path.join(blunDir, 'channels');
333
222
  const channelDir = path.join(channelsDir, 'telegram');
@@ -339,37 +228,7 @@ function installTelegramForProfile(packageRoot, blunDir) {
339
228
  } else {
340
229
  securePrivateFile(envFile);
341
230
  }
342
- }
343
-
344
- function prepareProfileRuntime(blunDir, callerCwd, mode) {
345
- ensurePrivateDirectory(blunDir);
346
- const cfgFile = path.join(blunDir, 'config.toml');
347
- if (fs.existsSync(cfgFile)) securePrivateFile(cfgFile);
348
- const standardMcpNames = availableStandardToolNames({ packageRoot: PKG })
349
- .filter((name) => name !== 'telegram');
350
- seedStandardTools({ packageRoot: PKG, blunDir, names: standardMcpNames });
351
- seedStandardDesignSkill({ packageRoot: PKG, blunDir });
352
- installManagedAgentSpinePlugin({ packageRoot: PKG, blunDir });
353
- if (mode === LAUNCHER_MODES.KING) installTelegramForProfile(PKG, blunDir);
354
- return repairConfiguredNativeModules({
355
- blunDir, callerCwd,
356
- onRepairStart() {
357
- process.stdout.write('BLUN richtet native Node.js-Module fuer die neue Laufzeit ein.\n');
358
- },
359
- });
360
- }
361
-
362
- async function withProfileRuntimeReservation(homeDir, work) {
363
- const result = await tryAcquireUpdateLease({ packageRoot: homeDir, role: 'profile' });
364
- if (!result.acquired) throw Object.assign(new Error(`PROFILE_RUNTIME_${result.reason.toUpperCase()}`),
365
- { code: result.reason === 'busy' ? 'PROFILE_RUNTIME_BUSY' : 'PROFILE_RUNTIME_UNAVAILABLE' });
366
- try {
367
- result.lease.assertOwned();
368
- const value = await work();
369
- result.lease.assertOwned();
370
- return value;
371
- } finally { await result.lease.release(); }
372
- }
231
+ }
373
232
 
374
233
  function spawnManagedLauncher(binary, cwd) {
375
234
  return new Promise((resolve, reject) => {
@@ -503,29 +362,18 @@ async function runLauncher(options = {}) {
503
362
  }
504
363
  process.stdout.write(launcherHelpText());
505
364
  const env = createLauncherEnvironment(process.env, mode, readPackageVersion());
506
- const informationalEnv = { ...process.env };
507
- delete informationalEnv.BLUN_HOME;
508
- const paths = resolveLauncherPrivatePaths({ env: informationalEnv });
509
- env.BLUN_HOME = paths.blunHome;
510
- if (PROFILE.name !== undefined) {
511
- env.BLUN_SHARED_HOME = paths.sharedHome;
512
- env.BLUN_PROFILE = PROFILE.name;
513
- }
365
+ const informationalEnv = { ...process.env };
366
+ delete informationalEnv.BLUN_HOME;
367
+ env.BLUN_HOME = resolveLauncherPrivatePaths({ env: informationalEnv }).blunHome;
514
368
  process.exitCode = await runInformationalCore(ARGS, env, callerCwd, releaseNotice);
515
369
  return;
516
370
  }
517
371
 
518
- let privatePaths;
519
- const getPrivatePaths = () => {
520
- if (!privatePaths) {
521
- const resolved = resolveLauncherPrivatePaths();
522
- if (PROFILE.implicit && !fs.existsSync(resolved.blunHome)) {
523
- throw new Error(`Profil ${PROFILE.name} gibt es nicht. Anlegen mit king --profile ${PROFILE.name}.`);
524
- }
525
- privatePaths = resolved;
526
- }
527
- return privatePaths;
528
- };
372
+ let privatePaths;
373
+ const getPrivatePaths = () => {
374
+ privatePaths ||= resolveLauncherPrivatePaths();
375
+ return privatePaths;
376
+ };
529
377
  const nodeRuntime = await prepareManagedNodeRuntime({
530
378
  getBlunDir: () => getPrivatePaths().blunHome,
531
379
  });
@@ -544,28 +392,15 @@ async function runLauncher(options = {}) {
544
392
  if (ARGS.some((arg) => arg === '--help' || arg === '-h')) {
545
393
  process.stdout.write(launcherHelpText());
546
394
  const env = createLauncherEnvironment(process.env, mode, readPackageVersion());
547
- const informationalEnv = { ...process.env };
548
- delete informationalEnv.BLUN_HOME;
549
- const paths = resolveLauncherPrivatePaths({ env: informationalEnv });
550
- env.BLUN_HOME = paths.blunHome;
551
- if (PROFILE.name !== undefined) {
552
- env.BLUN_SHARED_HOME = paths.sharedHome;
553
- env.BLUN_PROFILE = PROFILE.name;
554
- }
395
+ const informationalEnv = { ...process.env };
396
+ delete informationalEnv.BLUN_HOME;
397
+ env.BLUN_HOME = resolveLauncherPrivatePaths({ env: informationalEnv }).blunHome;
555
398
  process.exitCode = await superviseProtectedCore(ARGS, env, callerCwd, releaseNotice);
556
399
  return;
557
400
  }
558
401
 
559
- const blunDir = getPrivatePaths().blunHome;
560
- if (mode === LAUNCHER_MODES.KING && isInteractiveKingStart(ARGS)) {
561
- const activePid = runningTuiPid(blunDir);
562
- if (activePid !== null) {
563
- process.stderr.write(`King läuft bereits (PID ${activePid}).\n`);
564
- process.exitCode = 1;
565
- return;
566
- }
567
- }
568
- ensurePrivateDirectory(blunDir);
402
+ const blunDir = getPrivatePaths().blunHome;
403
+ ensurePrivateDirectory(blunDir);
569
404
 
570
405
  // --- 1. Oeffentlicher npm-Update-Dialog. -------------------------------
571
406
  const updateResult = options.skipUpdateNotice === true
@@ -596,53 +431,55 @@ async function runLauncher(options = {}) {
596
431
  // --- 2. Bestehende Konfiguration absichern -------------------------------
597
432
  // Ein frischer Start bleibt absichtlich ohne statischen Anbieter. /login
598
433
  // provisioniert King ueber den BLUN-OAuth-Server.
599
- require('./verify-bundled-agent-sources.cjs').verifyBundledAgentSources(PKG);
600
- const nativeModules = mode === LAUNCHER_MODES.KING && isInteractiveKingStart(ARGS)
601
- ? await withProfileRuntimeReservation(blunDir, () => prepareProfileRuntime(blunDir, callerCwd, mode))
602
- : prepareProfileRuntime(blunDir, callerCwd, mode);
434
+ const cfgFile = path.join(blunDir, 'config.toml');
435
+ if (fs.existsSync(cfgFile)) securePrivateFile(cfgFile);
436
+ require('./verify-bundled-agent-sources.cjs').verifyBundledAgentSources(PKG);
437
+
438
+ // --- 3. BLUN-Standard-MCPs additiv im Benutzerprofil einrichten ---------
439
+ const standardMcpNames = availableStandardToolNames({ packageRoot: PKG })
440
+ .filter((name) => name !== 'telegram');
441
+ seedStandardTools({
442
+ packageRoot: PKG,
443
+ blunDir,
444
+ names: standardMcpNames,
445
+ });
446
+
447
+ // --- 4. Eigenes BLUN-Grunddesign als einzigen Standard-Skill installieren
448
+ seedStandardDesignSkill({ packageRoot: PKG, blunDir });
449
+ installManagedAgentSpinePlugin({ packageRoot: PKG, blunDir });
603
450
 
451
+ // --- 5. Telegram-Plugin + Token-Vorlage (nur King) -----------------------
452
+ if (mode === LAUNCHER_MODES.KING) {
453
+ installTelegramForProfile(PKG, blunDir);
454
+ }
455
+
456
+ const nativeModules = repairConfiguredNativeModules({
457
+ blunDir,
458
+ callerCwd,
459
+ onRepairStart() {
460
+ process.stdout.write('BLUN richtet native Node.js-Module fuer die neue Laufzeit ein.\n');
461
+ },
462
+ });
604
463
  if (nativeModules.repaired.length > 0) {
605
464
  process.stdout.write('Native Node.js-Module sind wieder einsatzbereit.\n');
606
465
  }
607
466
 
608
- // --- 6. Start -----------------------------------------------------------
609
- const env = createLauncherEnvironment(process.env, mode, readPackageVersion(), blunDir);
610
- env.BLUN_HOME = blunDir;
611
- if (PROFILE.name !== undefined) {
612
- env.BLUN_SHARED_HOME = getPrivatePaths().sharedHome;
613
- env.BLUN_PROFILE = PROFILE.name;
614
- }
615
- const handoffOptions = mode === LAUNCHER_MODES.KING && isInteractiveKingStart(ARGS)
616
- ? { prepareProfile: async (selected) => {
617
- const target = selected.homeDir;
618
- await withProfileRuntimeReservation(target, () => prepareProfileRuntime(target, callerCwd, mode));
619
- const next = createLauncherEnvironment(process.env, mode, readPackageVersion(), target);
620
- next.BLUN_HOME = target;
621
- next.BLUN_SHARED_HOME = selected.sharedHome;
622
- next.BLUN_PROFILE = selected.name;
623
- delete next.BLUN_TELEGRAM_STATE_DIR;
624
- delete next.BLUN_PLUGIN_ROOT;
625
- return next;
626
- } } : {};
627
- if (handoffOptions.prepareProfile) env.BLUN_PROFILE_HANDOFF = '1';
628
- else delete env.BLUN_PROFILE_HANDOFF;
467
+ // --- 6. Start -----------------------------------------------------------
468
+ const env = createLauncherEnvironment(process.env, mode, readPackageVersion(), blunDir);
469
+ env.BLUN_HOME = blunDir;
629
470
  process.exitCode = await superviseProtectedCore(
630
471
  ARGS,
631
472
  env,
632
473
  callerCwd,
633
- releaseNotice,
634
- handoffOptions,
474
+ releaseNotice,
635
475
  );
636
476
  } finally {
637
477
  await releaseNotice();
638
478
  }
639
479
  }
640
480
 
641
- module.exports = {
642
- withProfileRuntimeReservation,
643
- resolveLauncherPrivatePaths,
644
- isInteractiveKingStart,
645
- runningTuiPid,
481
+ module.exports = {
482
+ resolveLauncherPrivatePaths,
646
483
  runLauncher,
647
484
  shouldDetachProtectedCore,
648
485
  spawnManagedLauncher,