blun-king-cli 9.1.602 → 9.1.603

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 (122) hide show
  1. package/CHANGELOG.md +103 -97
  2. package/LIESMICH.txt +57 -57
  3. package/README.md +90 -90
  4. package/bin/agentspine-king-goal-inbox.mjs +127 -127
  5. package/bin/agentspine-king-goal-intake.mjs +106 -106
  6. package/bin/agentspine-king-host-runner.mjs +109 -109
  7. package/bin/agentspine-king-snapshot-policy.cjs +80 -80
  8. package/bin/agentspine-king-status-policy.mjs +226 -226
  9. package/bin/agentspine-king-worker-host.mjs +160 -160
  10. package/bin/core-bootstrap.js +77 -77
  11. package/bin/launcher-mode.js +93 -93
  12. package/bin/launcher-restart-policy.cjs +131 -131
  13. package/bin/launcher-runtime.js +491 -491
  14. package/bin/managed-node.js +186 -186
  15. package/bin/managed-plugin-selection.cjs +115 -115
  16. package/bin/native-module-repair.js +201 -201
  17. package/bin/node-runtime.js +34 -34
  18. package/bin/node-version.js +49 -49
  19. package/bin/plugin-bootstrap.js +162 -162
  20. package/bin/private-paths.js +1606 -1606
  21. package/bin/runtime-exit-ledger.cjs +144 -144
  22. package/bin/runtime-exit-ledger.d.cts +23 -23
  23. package/bin/standard-tools-bootstrap.js +272 -272
  24. package/bin/turn-thinking-policy.cjs +82 -82
  25. package/bin/update-copy.js +200 -200
  26. package/bin/update-lease.js +597 -597
  27. package/bin/update-notice.js +1568 -1568
  28. package/bin/verify-agent-behavior.cjs +122 -122
  29. package/bin/verify-agent-components.cjs +104 -104
  30. package/bin/verify-bundled-agent-sources.cjs +83 -83
  31. package/bin/windows-node-crash-dump.cjs +289 -289
  32. package/blun.mjs +115 -7
  33. package/codebase-index/codebase_index.py +470 -470
  34. package/dist-web/assets/{CodeBlockNode-CXnTLMNr.js → CodeBlockNode-TKKkJX8L.js} +1 -1
  35. package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-CCF8Ntnq.js → CodeBlockShell.vue_vue_type_style_index_0_lang-CUj2Ds5x.js} +1 -1
  36. package/dist-web/assets/DesignSystemView-DwK1aQMo.js +12 -0
  37. package/dist-web/assets/DesignSystemView-szjTj7ns.css +1 -0
  38. package/dist-web/assets/{Tooltip-CFQEzqC-.js → Tooltip-CTWv7WCU.js} +1 -1
  39. package/dist-web/assets/{abnfDiagram-N423BO3Z-Z1APZG5m.js → abnfDiagram-N423BO3Z-DA8V8Zjh.js} +1 -1
  40. package/dist-web/assets/{arc-C4VyWloT.js → arc-YtddKbdY.js} +1 -1
  41. package/dist-web/assets/{architectureDiagram-T3A2C74G-DpddbUcM.js → architectureDiagram-T3A2C74G-CGEiObmo.js} +1 -1
  42. package/dist-web/assets/{blockDiagram-VBNYF7ZC-BqccOSMr.js → blockDiagram-VBNYF7ZC-Bd5Vt50e.js} +1 -1
  43. package/dist-web/assets/{c4Diagram-5PPSVZJV-OHAcJrTy.js → c4Diagram-5PPSVZJV-D2ApPM54.js} +1 -1
  44. package/dist-web/assets/channel-BnluexuN.js +1 -0
  45. package/dist-web/assets/{chunk-2GRJ4B5K-DqJHs8Fw.js → chunk-2GRJ4B5K-BDcIEZSl.js} +1 -1
  46. package/dist-web/assets/{chunk-2Q5K7J3B-B1nCd91o.js → chunk-2Q5K7J3B-6aSabCX7.js} +1 -1
  47. package/dist-web/assets/{chunk-5RXB4S5H-neG70kZx.js → chunk-5RXB4S5H-BFRQvIJS.js} +1 -1
  48. package/dist-web/assets/{chunk-5VM5RSS4-l7biGqeH.js → chunk-5VM5RSS4-ChAa-DNY.js} +1 -1
  49. package/dist-web/assets/{chunk-6Q2QTUOP-BO-F11Gs.js → chunk-6Q2QTUOP-BIfrb2Jc.js} +1 -1
  50. package/dist-web/assets/{chunk-GF5L2VYU-BtC69fw0.js → chunk-GF5L2VYU-BR0gvtWI.js} +1 -1
  51. package/dist-web/assets/{chunk-JWPE2WC7-DIOubEqr.js → chunk-JWPE2WC7-BgXKsx5E.js} +1 -1
  52. package/dist-web/assets/{chunk-KBJHAD2P-DDUeH_Ba.js → chunk-KBJHAD2P-I8mrZhpz.js} +1 -1
  53. package/dist-web/assets/{chunk-RYQCIY6F-B9gFMVbS.js → chunk-RYQCIY6F-BMPaem92.js} +1 -1
  54. package/dist-web/assets/{chunk-XXDRQBXY-Bn1Xz6TQ.js → chunk-XXDRQBXY-COy0J-0j.js} +1 -1
  55. package/dist-web/assets/classDiagram-JCYQIIEL-BliFdSD9.js +1 -0
  56. package/dist-web/assets/classDiagram-v2-OCEON4UE-BliFdSD9.js +1 -0
  57. package/dist-web/assets/{cose-bilkent-JH36ORCC-DqigO3T4.js → cose-bilkent-JH36ORCC-MosTTRdo.js} +1 -1
  58. package/dist-web/assets/{cynefin-VYW2F7L2-rpD93tQ-.js → cynefin-VYW2F7L2-5tjPgrkP.js} +1 -1
  59. package/dist-web/assets/{cynefinDiagram-MW4NZA55-DbTqnkVJ.js → cynefinDiagram-MW4NZA55-CbDcdInR.js} +1 -1
  60. package/dist-web/assets/{dagre-VZM6K2ZE-DcM8aEVY.js → dagre-VZM6K2ZE-YaBom1ZH.js} +1 -1
  61. package/dist-web/assets/{diagram-7IWD3JNH-UymgsBNa.js → diagram-7IWD3JNH-Da4m-Hgz.js} +1 -1
  62. package/dist-web/assets/{diagram-B4RE2ZJO-BiYu5WPF.js → diagram-B4RE2ZJO-CAUUegxg.js} +1 -1
  63. package/dist-web/assets/{diagram-LBJQPF4R-BD3kkgOO.js → diagram-LBJQPF4R-o21mWKG4.js} +1 -1
  64. package/dist-web/assets/{diagram-Q27KOJAE-D1mYQ_cI.js → diagram-Q27KOJAE-BA3z3sXf.js} +1 -1
  65. package/dist-web/assets/{diagram-UB23O5K3-BtX8u6HG.js → diagram-UB23O5K3-CGRdSSDK.js} +1 -1
  66. package/dist-web/assets/{ebnfDiagram-BXEA7PRR-CBAnFkRF.js → ebnfDiagram-BXEA7PRR-Bw-iU9FP.js} +1 -1
  67. package/dist-web/assets/{erDiagram-JOGREHBK-3vKcWsxm.js → erDiagram-JOGREHBK-BwM1yiR0.js} +1 -1
  68. package/dist-web/assets/{flowDiagram-UKHOOZJN-D9wBbHm2.js → flowDiagram-UKHOOZJN-z05eOR1Q.js} +1 -1
  69. package/dist-web/assets/{ganttDiagram-PKOTCBZU-Cd_dViF-.js → ganttDiagram-PKOTCBZU-BMUubNTl.js} +1 -1
  70. package/dist-web/assets/{gitGraphDiagram-DS77QQ5N-BiEEtTo7.js → gitGraphDiagram-DS77QQ5N-Dccbi1wU.js} +1 -1
  71. package/dist-web/assets/{index-DdEakFJM.js → index-BBbC5LRF.js} +1 -1
  72. package/dist-web/assets/{index-BmKj7CB1.css → index-C9eDH3u-.css} +1 -1
  73. package/dist-web/assets/{index-Ba1OvLjf.js → index-D48p0M2S.js} +2 -2
  74. package/dist-web/assets/{index-CiPA8Kex.js → index-h0KEOmkU.js} +14 -14
  75. package/dist-web/assets/{index10-CNr4U-Nw.js → index10-Qbuw1N6u.js} +1 -1
  76. package/dist-web/assets/{index11-Dto_yZNz.js → index11-g8v025wN.js} +1 -1
  77. package/dist-web/assets/{index5-B2PldaO2.js → index5-BYNcV8BY.js} +1 -1
  78. package/dist-web/assets/{index6-CBdZmmyx.js → index6-BetANtnV.js} +1 -1
  79. package/dist-web/assets/{index7-Dz9oCsUF.js → index7-BcPbgCKN.js} +1 -1
  80. package/dist-web/assets/{index8-B6k25jtU.js → index8-B1lp-RvF.js} +2 -2
  81. package/dist-web/assets/{infoDiagram-6WML65LV-D4ph2sIH.js → infoDiagram-6WML65LV-BF_pbUnN.js} +1 -1
  82. package/dist-web/assets/{ishikawaDiagram-WSZJBQD7-DjKjbMm9.js → ishikawaDiagram-WSZJBQD7-Dedv4urS.js} +1 -1
  83. package/dist-web/assets/{journeyDiagram-NVQOT4AX-DttHDfPQ.js → journeyDiagram-NVQOT4AX-B1Ex3b6o.js} +1 -1
  84. package/dist-web/assets/{kanban-definition-27J2QSJJ-C5gB-W0d.js → kanban-definition-27J2QSJJ-BtCGliBH.js} +1 -1
  85. package/dist-web/assets/{linear-BRGe4-d6.js → linear-ByItc8Qr.js} +1 -1
  86. package/dist-web/assets/{mermaid.core-D-9Sx1No.js → mermaid.core-B1M2O7nN.js} +4 -4
  87. package/dist-web/assets/{mindmap-definition-FAOFIHXS-Cg_hoVIq.js → mindmap-definition-FAOFIHXS-D0UHKUyj.js} +1 -1
  88. package/dist-web/assets/{pegDiagram-VL7TDLO6-CSX9hitD.js → pegDiagram-VL7TDLO6-D7zYCVmG.js} +1 -1
  89. package/dist-web/assets/{pieDiagram-7S7Q4E2Y-0L0mxahZ.js → pieDiagram-7S7Q4E2Y-Bd0i9CHa.js} +1 -1
  90. package/dist-web/assets/{quadrantDiagram-CIZ2JOQS-U483z0er.js → quadrantDiagram-CIZ2JOQS-MG-Ug47d.js} +1 -1
  91. package/dist-web/assets/{railroadDiagram-AXF67PYL-D80a2_DJ.js → railroadDiagram-AXF67PYL-AZdl90Gj.js} +1 -1
  92. package/dist-web/assets/{requirementDiagram-LRYGKXZP-CeyHfq8t.js → requirementDiagram-LRYGKXZP-DjplF9kt.js} +1 -1
  93. package/dist-web/assets/{sankeyDiagram-W5VNT64P-CCISkkrR.js → sankeyDiagram-W5VNT64P-Bi9Zgfjs.js} +1 -1
  94. package/dist-web/assets/{sequenceDiagram-SI44F4Z6-jQfm2XS7.js → sequenceDiagram-SI44F4Z6-ChEpdCvb.js} +1 -1
  95. package/dist-web/assets/{sizeCapture-X5ZJPWSS-lRZsmCoS.js → sizeCapture-X5ZJPWSS-B5RFUdaa.js} +1 -1
  96. package/dist-web/assets/{stateDiagram-OKZ733FA-ClCgTdUm.js → stateDiagram-OKZ733FA-BkRblSKp.js} +1 -1
  97. package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fVkQcACW.js +1 -0
  98. package/dist-web/assets/{swimlanes-SLNWSIFB-BCdOUN05.js → swimlanes-SLNWSIFB-DLXH6Zhc.js} +2 -2
  99. package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-Bg-BiZJQ.js +8 -0
  100. package/dist-web/assets/{timeline-definition-Z64GVDOM-DpWutSKa.js → timeline-definition-Z64GVDOM-C_N88siO.js} +1 -1
  101. package/dist-web/assets/{vennDiagram-T6HMQDX7-DVC5JVsc.js → vennDiagram-T6HMQDX7-DMsnvDt0.js} +1 -1
  102. package/dist-web/assets/{vue.runtime.esm-bundler-BwwRtQwQ.js → vue.runtime.esm-bundler-B-3uIy85.js} +1 -1
  103. package/dist-web/assets/{wardleyDiagram-T6FBY63Y-BK2mrq7L.js → wardleyDiagram-T6FBY63Y-C9SJIPzq.js} +1 -1
  104. package/dist-web/assets/{xychartDiagram-ELKLHX3M-DUJu9F7-.js → xychartDiagram-ELKLHX3M-DZLWA6Go.js} +1 -1
  105. package/dist-web/index.html +32 -32
  106. package/dist-web/vis/index.html.gz +0 -0
  107. package/package.json +1 -1
  108. package/scripts/fix-node-pty-perms.js +53 -53
  109. package/standard-skills/blun-app-design-system/SKILL.md +30 -30
  110. package/standard-skills/blun-app-design-system/provenance.json +17 -17
  111. package/standard-skills/blun-app-design-system/references/tokens.md +48 -48
  112. package/standard-skills/blun-app-design-system/scripts/check-blun-design.mjs +49 -49
  113. package/telegram-plugin/blun.plugin.json +20 -20
  114. package/telegram-plugin/commands/access.md +37 -37
  115. package/worker-host.mjs +5 -5
  116. package/dist-web/assets/DesignSystemView-6HgAUEmC.css +0 -1
  117. package/dist-web/assets/DesignSystemView-BbMOu-XO.js +0 -12
  118. package/dist-web/assets/channel-B2VOQOI-.js +0 -1
  119. package/dist-web/assets/classDiagram-JCYQIIEL-BA1TjAxj.js +0 -1
  120. package/dist-web/assets/classDiagram-v2-OCEON4UE-BA1TjAxj.js +0 -1
  121. package/dist-web/assets/stateDiagram-v2-UEYNNEHI-fi_lrTAx.js +0 -1
  122. package/dist-web/assets/swimlanesDiagram-ULZ7WXOC-BUd_uYK3.js +0 -8
@@ -1,201 +1,201 @@
1
- 'use strict';
2
-
3
- const { spawnSync } = require('node:child_process');
4
- const fs = require('node:fs');
5
- const path = require('node:path');
6
-
7
- const SQLITE_PROBE = [
8
- "const Database = require('better-sqlite3');",
9
- "const db = new Database(':memory:');",
10
- "const row = db.prepare('SELECT 1 AS ok').get();",
11
- 'db.close();',
12
- "if (row?.ok !== 1) throw new Error('SQLITE_PROBE_FAILED');",
13
- ].join(' ');
14
-
15
- function commandFailure(result) {
16
- return String(result?.stderr || result?.stdout || result?.error?.message || '').trim();
17
- }
18
-
19
- function packageHasDependency(document, dependency) {
20
- return ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies']
21
- .some((field) => Object.hasOwn(document?.[field] || {}, dependency));
22
- }
23
-
24
- function nearestPackageDirectory(startDir) {
25
- let current = path.resolve(startDir);
26
- while (true) {
27
- if (fs.existsSync(path.join(current, 'package.json'))) return current;
28
- const parent = path.dirname(current);
29
- if (parent === current) return null;
30
- current = parent;
31
- }
32
- }
33
-
34
- function projectRoot(startDir) {
35
- let current = path.resolve(startDir);
36
- while (true) {
37
- if (fs.existsSync(path.join(current, '.git'))) return current;
38
- const parent = path.dirname(current);
39
- if (parent === current) return path.resolve(startDir);
40
- current = parent;
41
- }
42
- }
43
-
44
- function readMcpDocument(configPath) {
45
- if (!fs.existsSync(configPath)) return null;
46
- try {
47
- const document = JSON.parse(fs.readFileSync(configPath, 'utf8'));
48
- return document && typeof document === 'object' ? document : null;
49
- } catch {
50
- return null;
51
- }
52
- }
53
-
54
- function serverProjectDirectory(server, configPath) {
55
- if (!server || typeof server !== 'object' || server.enabled === false) return null;
56
- if (typeof server.cwd === 'string' && server.cwd.trim()) {
57
- const cwd = server.cwd.trim();
58
- return nearestPackageDirectory(
59
- path.isAbsolute(cwd) ? cwd : path.resolve(path.dirname(configPath), cwd),
60
- );
61
- }
62
- const args = Array.isArray(server.args) ? server.args : [];
63
- const script = args.find((arg) => typeof arg === 'string' && /\.[cm]?js$/iu.test(arg));
64
- if (!script) return null;
65
- const scriptPath = path.isAbsolute(script)
66
- ? script
67
- : path.resolve(path.dirname(configPath), script);
68
- return nearestPackageDirectory(path.dirname(scriptPath));
69
- }
70
-
71
- function configuredNativeProjectPaths({ blunDir, callerCwd }) {
72
- const root = projectRoot(callerCwd);
73
- const configPaths = [...new Set([
74
- path.join(blunDir, 'mcp.json'),
75
- path.join(root, '.mcp.json'),
76
- path.join(callerCwd, '.blun', 'mcp.json'),
77
- ].map((entry) => path.resolve(entry)))];
78
- const candidates = [nearestPackageDirectory(callerCwd)];
79
- for (const configPath of configPaths) {
80
- const document = readMcpDocument(configPath);
81
- const servers = document?.mcpServers;
82
- if (!servers || typeof servers !== 'object' || Array.isArray(servers)) continue;
83
- for (const server of Object.values(servers)) {
84
- candidates.push(serverProjectDirectory(server, configPath));
85
- }
86
- }
87
-
88
- const seen = new Set();
89
- const projects = [];
90
- for (const candidate of candidates) {
91
- if (!candidate) continue;
92
- const absolute = path.resolve(candidate);
93
- const key = process.platform === 'win32' ? absolute.toLowerCase() : absolute;
94
- if (seen.has(key)) continue;
95
- seen.add(key);
96
- projects.push(absolute);
97
- }
98
- return projects;
99
- }
100
-
101
- function probeBetterSqlite({ nodeBinary, projectDir, spawnSyncImpl }) {
102
- return spawnSyncImpl(nodeBinary, ['-e', SQLITE_PROBE], {
103
- cwd: projectDir,
104
- encoding: 'utf8',
105
- timeout: 30_000,
106
- windowsHide: true,
107
- });
108
- }
109
-
110
- function npmInvocation(nodeBinary) {
111
- const candidates = [
112
- path.join(path.dirname(nodeBinary), 'node_modules', 'npm', 'bin', 'npm-cli.js'),
113
- path.resolve(path.dirname(nodeBinary), '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js'),
114
- ];
115
- const npmCli = candidates.find((candidate) => fs.existsSync(candidate));
116
- if (!npmCli) {
117
- throw new Error('npm-cli.js wurde fuer die aktive Node.js-Laufzeit nicht gefunden.');
118
- }
119
- return { args: [npmCli], command: nodeBinary };
120
- }
121
-
122
- function repairNativeProject({
123
- nodeBinary = process.execPath,
124
- npmCommand,
125
- onRepairStart,
126
- projectDir,
127
- spawnSyncImpl = spawnSync,
128
- }) {
129
- if (typeof projectDir !== 'string' || !path.isAbsolute(projectDir)) {
130
- throw new Error('Der Projektpfad fuer die native Ladeprobe muss absolut sein.');
131
- }
132
- const absoluteProjectDir = path.resolve(projectDir);
133
- const packagePath = path.join(absoluteProjectDir, 'package.json');
134
- let packageDocument;
135
- try {
136
- packageDocument = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
137
- } catch {
138
- return { kind: 'skipped', reason: 'package_unreadable' };
139
- }
140
- if (!packageHasDependency(packageDocument, 'better-sqlite3')) {
141
- return { kind: 'skipped', reason: 'dependency_missing' };
142
- }
143
-
144
- const before = probeBetterSqlite({ nodeBinary, projectDir: absoluteProjectDir, spawnSyncImpl });
145
- if (before.status === 0) return { kind: 'healthy' };
146
-
147
- const npm = npmCommand === undefined
148
- ? npmInvocation(nodeBinary)
149
- : { args: [], command: npmCommand };
150
- onRepairStart?.(absoluteProjectDir);
151
- const rebuilt = spawnSyncImpl(npm.command, [...npm.args, 'rebuild', 'better-sqlite3'], {
152
- cwd: absoluteProjectDir,
153
- encoding: 'utf8',
154
- timeout: 300_000,
155
- windowsHide: true,
156
- });
157
- if (rebuilt.status !== 0) {
158
- throw new Error(
159
- `Native Node.js-Module konnten nicht repariert werden: ${commandFailure(rebuilt) || 'ohne Fehlertext'}`,
160
- );
161
- }
162
-
163
- const after = probeBetterSqlite({ nodeBinary, projectDir: absoluteProjectDir, spawnSyncImpl });
164
- if (after.status !== 0) {
165
- throw new Error(
166
- `Ladeprobe nach dem Rebuild fehlgeschlagen: ${commandFailure(after) || 'ohne Fehlertext'}`,
167
- );
168
- }
169
- return { kind: 'repaired' };
170
- }
171
-
172
- function repairConfiguredNativeModules({
173
- blunDir,
174
- callerCwd,
175
- nodeBinary = process.execPath,
176
- onRepairStart,
177
- projectPaths,
178
- repairProject = repairNativeProject,
179
- spawnSyncImpl = spawnSync,
180
- }) {
181
- const projects = projectPaths || configuredNativeProjectPaths({ blunDir, callerCwd });
182
- const result = { checked: projects.length, healthy: [], repaired: [], skipped: [] };
183
- for (const projectDir of projects) {
184
- const firstResult = repairProject({
185
- nodeBinary,
186
- projectDir,
187
- spawnSyncImpl,
188
- onRepairStart,
189
- });
190
- if (firstResult.kind === 'healthy') result.healthy.push(projectDir);
191
- else if (firstResult.kind === 'repaired') result.repaired.push(projectDir);
192
- else result.skipped.push(projectDir);
193
- }
194
- return result;
195
- }
196
-
197
- module.exports = {
198
- configuredNativeProjectPaths,
199
- repairConfiguredNativeModules,
200
- repairNativeProject,
201
- };
1
+ 'use strict';
2
+
3
+ const { spawnSync } = require('node:child_process');
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+
7
+ const SQLITE_PROBE = [
8
+ "const Database = require('better-sqlite3');",
9
+ "const db = new Database(':memory:');",
10
+ "const row = db.prepare('SELECT 1 AS ok').get();",
11
+ 'db.close();',
12
+ "if (row?.ok !== 1) throw new Error('SQLITE_PROBE_FAILED');",
13
+ ].join(' ');
14
+
15
+ function commandFailure(result) {
16
+ return String(result?.stderr || result?.stdout || result?.error?.message || '').trim();
17
+ }
18
+
19
+ function packageHasDependency(document, dependency) {
20
+ return ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies']
21
+ .some((field) => Object.hasOwn(document?.[field] || {}, dependency));
22
+ }
23
+
24
+ function nearestPackageDirectory(startDir) {
25
+ let current = path.resolve(startDir);
26
+ while (true) {
27
+ if (fs.existsSync(path.join(current, 'package.json'))) return current;
28
+ const parent = path.dirname(current);
29
+ if (parent === current) return null;
30
+ current = parent;
31
+ }
32
+ }
33
+
34
+ function projectRoot(startDir) {
35
+ let current = path.resolve(startDir);
36
+ while (true) {
37
+ if (fs.existsSync(path.join(current, '.git'))) return current;
38
+ const parent = path.dirname(current);
39
+ if (parent === current) return path.resolve(startDir);
40
+ current = parent;
41
+ }
42
+ }
43
+
44
+ function readMcpDocument(configPath) {
45
+ if (!fs.existsSync(configPath)) return null;
46
+ try {
47
+ const document = JSON.parse(fs.readFileSync(configPath, 'utf8'));
48
+ return document && typeof document === 'object' ? document : null;
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
53
+
54
+ function serverProjectDirectory(server, configPath) {
55
+ if (!server || typeof server !== 'object' || server.enabled === false) return null;
56
+ if (typeof server.cwd === 'string' && server.cwd.trim()) {
57
+ const cwd = server.cwd.trim();
58
+ return nearestPackageDirectory(
59
+ path.isAbsolute(cwd) ? cwd : path.resolve(path.dirname(configPath), cwd),
60
+ );
61
+ }
62
+ const args = Array.isArray(server.args) ? server.args : [];
63
+ const script = args.find((arg) => typeof arg === 'string' && /\.[cm]?js$/iu.test(arg));
64
+ if (!script) return null;
65
+ const scriptPath = path.isAbsolute(script)
66
+ ? script
67
+ : path.resolve(path.dirname(configPath), script);
68
+ return nearestPackageDirectory(path.dirname(scriptPath));
69
+ }
70
+
71
+ function configuredNativeProjectPaths({ blunDir, callerCwd }) {
72
+ const root = projectRoot(callerCwd);
73
+ const configPaths = [...new Set([
74
+ path.join(blunDir, 'mcp.json'),
75
+ path.join(root, '.mcp.json'),
76
+ path.join(callerCwd, '.blun', 'mcp.json'),
77
+ ].map((entry) => path.resolve(entry)))];
78
+ const candidates = [nearestPackageDirectory(callerCwd)];
79
+ for (const configPath of configPaths) {
80
+ const document = readMcpDocument(configPath);
81
+ const servers = document?.mcpServers;
82
+ if (!servers || typeof servers !== 'object' || Array.isArray(servers)) continue;
83
+ for (const server of Object.values(servers)) {
84
+ candidates.push(serverProjectDirectory(server, configPath));
85
+ }
86
+ }
87
+
88
+ const seen = new Set();
89
+ const projects = [];
90
+ for (const candidate of candidates) {
91
+ if (!candidate) continue;
92
+ const absolute = path.resolve(candidate);
93
+ const key = process.platform === 'win32' ? absolute.toLowerCase() : absolute;
94
+ if (seen.has(key)) continue;
95
+ seen.add(key);
96
+ projects.push(absolute);
97
+ }
98
+ return projects;
99
+ }
100
+
101
+ function probeBetterSqlite({ nodeBinary, projectDir, spawnSyncImpl }) {
102
+ return spawnSyncImpl(nodeBinary, ['-e', SQLITE_PROBE], {
103
+ cwd: projectDir,
104
+ encoding: 'utf8',
105
+ timeout: 30_000,
106
+ windowsHide: true,
107
+ });
108
+ }
109
+
110
+ function npmInvocation(nodeBinary) {
111
+ const candidates = [
112
+ path.join(path.dirname(nodeBinary), 'node_modules', 'npm', 'bin', 'npm-cli.js'),
113
+ path.resolve(path.dirname(nodeBinary), '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js'),
114
+ ];
115
+ const npmCli = candidates.find((candidate) => fs.existsSync(candidate));
116
+ if (!npmCli) {
117
+ throw new Error('npm-cli.js wurde fuer die aktive Node.js-Laufzeit nicht gefunden.');
118
+ }
119
+ return { args: [npmCli], command: nodeBinary };
120
+ }
121
+
122
+ function repairNativeProject({
123
+ nodeBinary = process.execPath,
124
+ npmCommand,
125
+ onRepairStart,
126
+ projectDir,
127
+ spawnSyncImpl = spawnSync,
128
+ }) {
129
+ if (typeof projectDir !== 'string' || !path.isAbsolute(projectDir)) {
130
+ throw new Error('Der Projektpfad fuer die native Ladeprobe muss absolut sein.');
131
+ }
132
+ const absoluteProjectDir = path.resolve(projectDir);
133
+ const packagePath = path.join(absoluteProjectDir, 'package.json');
134
+ let packageDocument;
135
+ try {
136
+ packageDocument = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
137
+ } catch {
138
+ return { kind: 'skipped', reason: 'package_unreadable' };
139
+ }
140
+ if (!packageHasDependency(packageDocument, 'better-sqlite3')) {
141
+ return { kind: 'skipped', reason: 'dependency_missing' };
142
+ }
143
+
144
+ const before = probeBetterSqlite({ nodeBinary, projectDir: absoluteProjectDir, spawnSyncImpl });
145
+ if (before.status === 0) return { kind: 'healthy' };
146
+
147
+ const npm = npmCommand === undefined
148
+ ? npmInvocation(nodeBinary)
149
+ : { args: [], command: npmCommand };
150
+ onRepairStart?.(absoluteProjectDir);
151
+ const rebuilt = spawnSyncImpl(npm.command, [...npm.args, 'rebuild', 'better-sqlite3'], {
152
+ cwd: absoluteProjectDir,
153
+ encoding: 'utf8',
154
+ timeout: 300_000,
155
+ windowsHide: true,
156
+ });
157
+ if (rebuilt.status !== 0) {
158
+ throw new Error(
159
+ `Native Node.js-Module konnten nicht repariert werden: ${commandFailure(rebuilt) || 'ohne Fehlertext'}`,
160
+ );
161
+ }
162
+
163
+ const after = probeBetterSqlite({ nodeBinary, projectDir: absoluteProjectDir, spawnSyncImpl });
164
+ if (after.status !== 0) {
165
+ throw new Error(
166
+ `Ladeprobe nach dem Rebuild fehlgeschlagen: ${commandFailure(after) || 'ohne Fehlertext'}`,
167
+ );
168
+ }
169
+ return { kind: 'repaired' };
170
+ }
171
+
172
+ function repairConfiguredNativeModules({
173
+ blunDir,
174
+ callerCwd,
175
+ nodeBinary = process.execPath,
176
+ onRepairStart,
177
+ projectPaths,
178
+ repairProject = repairNativeProject,
179
+ spawnSyncImpl = spawnSync,
180
+ }) {
181
+ const projects = projectPaths || configuredNativeProjectPaths({ blunDir, callerCwd });
182
+ const result = { checked: projects.length, healthy: [], repaired: [], skipped: [] };
183
+ for (const projectDir of projects) {
184
+ const firstResult = repairProject({
185
+ nodeBinary,
186
+ projectDir,
187
+ spawnSyncImpl,
188
+ onRepairStart,
189
+ });
190
+ if (firstResult.kind === 'healthy') result.healthy.push(projectDir);
191
+ else if (firstResult.kind === 'repaired') result.repaired.push(projectDir);
192
+ else result.skipped.push(projectDir);
193
+ }
194
+ return result;
195
+ }
196
+
197
+ module.exports = {
198
+ configuredNativeProjectPaths,
199
+ repairConfiguredNativeModules,
200
+ repairNativeProject,
201
+ };
@@ -1,34 +1,34 @@
1
- 'use strict';
2
-
3
- const { ensureManagedNode } = require('./managed-node');
4
- const { unsupportedNodeMessage } = require('./node-version');
5
-
6
- async function prepareManagedNodeRuntime(options = {}) {
7
- const version = options.version || process.versions.node;
8
- const platform = options.platform || process.platform;
9
- const arch = options.arch || process.arch;
10
- const message = unsupportedNodeMessage(version, platform);
11
- if (message === null) return { kind: 'current' };
12
- if (platform !== 'darwin' && platform !== 'win32') return { kind: 'failed', message };
13
-
14
- try {
15
- const blunDir = options.blunDir || options.getBlunDir?.();
16
- const binary = await (options.ensureManagedNode || ensureManagedNode)(
17
- blunDir,
18
- platform,
19
- arch,
20
- );
21
- return { binary, kind: 'managed' };
22
- } catch (error) {
23
- return {
24
- kind: 'failed',
25
- message: [
26
- 'Die automatische Node.js-Einrichtung ist fehlgeschlagen.',
27
- error && error.message ? error.message : String(error),
28
- message,
29
- ].join('\n'),
30
- };
31
- }
32
- }
33
-
34
- module.exports = { prepareManagedNodeRuntime };
1
+ 'use strict';
2
+
3
+ const { ensureManagedNode } = require('./managed-node');
4
+ const { unsupportedNodeMessage } = require('./node-version');
5
+
6
+ async function prepareManagedNodeRuntime(options = {}) {
7
+ const version = options.version || process.versions.node;
8
+ const platform = options.platform || process.platform;
9
+ const arch = options.arch || process.arch;
10
+ const message = unsupportedNodeMessage(version, platform);
11
+ if (message === null) return { kind: 'current' };
12
+ if (platform !== 'darwin' && platform !== 'win32') return { kind: 'failed', message };
13
+
14
+ try {
15
+ const blunDir = options.blunDir || options.getBlunDir?.();
16
+ const binary = await (options.ensureManagedNode || ensureManagedNode)(
17
+ blunDir,
18
+ platform,
19
+ arch,
20
+ );
21
+ return { binary, kind: 'managed' };
22
+ } catch (error) {
23
+ return {
24
+ kind: 'failed',
25
+ message: [
26
+ 'Die automatische Node.js-Einrichtung ist fehlgeschlagen.',
27
+ error && error.message ? error.message : String(error),
28
+ message,
29
+ ].join('\n'),
30
+ };
31
+ }
32
+ }
33
+
34
+ module.exports = { prepareManagedNodeRuntime };
@@ -1,49 +1,49 @@
1
- 'use strict';
2
-
3
- const MINIMUM_NODE_VERSION = '24.15.0';
4
-
5
- function parseNodeVersion(version) {
6
- const match = /^(\d+)\.(\d+)\.(\d+)/.exec(String(version));
7
- return match ? match.slice(1).map(Number) : null;
8
- }
9
-
10
- function supportsNodeVersion(version) {
11
- const actual = parseNodeVersion(version);
12
- const minimum = parseNodeVersion(MINIMUM_NODE_VERSION);
13
- if (!actual || !minimum) return false;
14
-
15
- for (let index = 0; index < minimum.length; index += 1) {
16
- if (actual[index] > minimum[index]) return true;
17
- if (actual[index] < minimum[index]) return false;
18
- }
19
- return true;
20
- }
21
-
22
- function unsupportedNodeMessage(version, platform) {
23
- if (supportsNodeVersion(version)) return null;
24
-
25
- const lines = [
26
- '',
27
- 'BLUN kann mit dieser Node.js-Version nicht starten.',
28
- `Installiert: Node.js ${version}`,
29
- `Benoetigt: Node.js ${MINIMUM_NODE_VERSION} oder neuer`,
30
- '',
31
- ];
32
-
33
- if (platform === 'darwin') {
34
- lines.push(`Falls die automatische Einrichtung scheitert: nvm install ${MINIMUM_NODE_VERSION}`);
35
- } else if (platform === 'win32') {
36
- lines.push(`Falls die automatische Einrichtung scheitert: Node.js ${MINIMUM_NODE_VERSION} oder neuer von https://nodejs.org/ installieren.`);
37
- } else {
38
- lines.push(`Node.js ${MINIMUM_NODE_VERSION} oder neuer installieren: https://nodejs.org/`);
39
- }
40
- lines.push('Danach BLUN aktualisieren: npm i -g blun-king-cli@latest', '');
41
- return lines.join('\n');
42
- }
43
-
44
- module.exports = {
45
- MINIMUM_NODE_VERSION,
46
- parseNodeVersion,
47
- supportsNodeVersion,
48
- unsupportedNodeMessage,
49
- };
1
+ 'use strict';
2
+
3
+ const MINIMUM_NODE_VERSION = '24.15.0';
4
+
5
+ function parseNodeVersion(version) {
6
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(String(version));
7
+ return match ? match.slice(1).map(Number) : null;
8
+ }
9
+
10
+ function supportsNodeVersion(version) {
11
+ const actual = parseNodeVersion(version);
12
+ const minimum = parseNodeVersion(MINIMUM_NODE_VERSION);
13
+ if (!actual || !minimum) return false;
14
+
15
+ for (let index = 0; index < minimum.length; index += 1) {
16
+ if (actual[index] > minimum[index]) return true;
17
+ if (actual[index] < minimum[index]) return false;
18
+ }
19
+ return true;
20
+ }
21
+
22
+ function unsupportedNodeMessage(version, platform) {
23
+ if (supportsNodeVersion(version)) return null;
24
+
25
+ const lines = [
26
+ '',
27
+ 'BLUN kann mit dieser Node.js-Version nicht starten.',
28
+ `Installiert: Node.js ${version}`,
29
+ `Benoetigt: Node.js ${MINIMUM_NODE_VERSION} oder neuer`,
30
+ '',
31
+ ];
32
+
33
+ if (platform === 'darwin') {
34
+ lines.push(`Falls die automatische Einrichtung scheitert: nvm install ${MINIMUM_NODE_VERSION}`);
35
+ } else if (platform === 'win32') {
36
+ lines.push(`Falls die automatische Einrichtung scheitert: Node.js ${MINIMUM_NODE_VERSION} oder neuer von https://nodejs.org/ installieren.`);
37
+ } else {
38
+ lines.push(`Node.js ${MINIMUM_NODE_VERSION} oder neuer installieren: https://nodejs.org/`);
39
+ }
40
+ lines.push('Danach BLUN aktualisieren: npm i -g blun-king-cli@latest', '');
41
+ return lines.join('\n');
42
+ }
43
+
44
+ module.exports = {
45
+ MINIMUM_NODE_VERSION,
46
+ parseNodeVersion,
47
+ supportsNodeVersion,
48
+ unsupportedNodeMessage,
49
+ };