blun-king-cli 9.1.422 → 9.1.424
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/bin/launcher-runtime.js +30 -2
- package/bin/mistake-relevance-policy.cjs +61 -8
- package/bin/runtime-exit-ledger.cjs +143 -0
- package/blun.mjs +56 -1
- package/package.json +1 -1
package/bin/launcher-runtime.js
CHANGED
|
@@ -29,6 +29,7 @@ const { CORE_LOADED_MESSAGE } = require('./core-bootstrap');
|
|
|
29
29
|
const { prepareManagedNodeRuntime } = require('./node-runtime');
|
|
30
30
|
const { repairConfiguredNativeModules } = require('./native-module-repair');
|
|
31
31
|
const { startMnemoConnectHeartbeat } = require('./mnemo-connect-heartbeat.cjs');
|
|
32
|
+
const { recordRuntimeExit } = require('./runtime-exit-ledger.cjs');
|
|
32
33
|
const { acquireSharedRuntimeLease } = require('./update-lease');
|
|
33
34
|
const { runExplicitUpdate, runUpdateNotice } = require('./update-notice');
|
|
34
35
|
const {
|
|
@@ -218,8 +219,35 @@ async function superviseProtectedCore(args, env, cwd, releaseLauncherLeases, opt
|
|
|
218
219
|
const loaded = await core.loaded;
|
|
219
220
|
if (loaded) await releaseLauncherLeases();
|
|
220
221
|
const result = await core.completed;
|
|
221
|
-
if (result.error)
|
|
222
|
-
|
|
222
|
+
if (result.error) {
|
|
223
|
+
recordRuntimeExit({
|
|
224
|
+
homeDir: env.BLUN_HOME,
|
|
225
|
+
source: 'launcher',
|
|
226
|
+
kind: 'child-error',
|
|
227
|
+
exitCode: 1,
|
|
228
|
+
phase: loaded ? 'runtime' : 'startup',
|
|
229
|
+
cliVersion: env.BLUN_PUBLIC_PACKAGE_VERSION,
|
|
230
|
+
profile: env.BLUN_PROFILE,
|
|
231
|
+
loaded,
|
|
232
|
+
childPid: core.child?.pid,
|
|
233
|
+
error: result.error,
|
|
234
|
+
});
|
|
235
|
+
throw result.error;
|
|
236
|
+
}
|
|
237
|
+
const exitCode = exitCodeForChild(result, loaded);
|
|
238
|
+
recordRuntimeExit({
|
|
239
|
+
homeDir: env.BLUN_HOME,
|
|
240
|
+
source: 'launcher',
|
|
241
|
+
kind: 'child-exit',
|
|
242
|
+
exitCode,
|
|
243
|
+
signal: result.signal,
|
|
244
|
+
phase: loaded ? 'runtime' : 'startup',
|
|
245
|
+
cliVersion: env.BLUN_PUBLIC_PACKAGE_VERSION,
|
|
246
|
+
profile: env.BLUN_PROFILE,
|
|
247
|
+
loaded,
|
|
248
|
+
childPid: core.child?.pid,
|
|
249
|
+
});
|
|
250
|
+
return exitCode;
|
|
223
251
|
}
|
|
224
252
|
|
|
225
253
|
function installTelegramForProfile(packageRoot, blunDir) {
|
|
@@ -14,7 +14,8 @@ const NON_ACTIONABLE_USER_ORIGINS = new Set([
|
|
|
14
14
|
'skill_activation',
|
|
15
15
|
]);
|
|
16
16
|
const STOP_WORDS = new Set([
|
|
17
|
-
'aber', 'alle', 'alles', 'auch', '
|
|
17
|
+
'aber', 'alle', 'alles', 'auch', 'das', 'dem', 'den', 'der', 'des', 'die',
|
|
18
|
+
'ein', 'eine', 'einem', 'einen', 'einer', 'eines',
|
|
18
19
|
'fuer', 'haben', 'hier', 'immer', 'jetzt', 'kann', 'machen', 'mehr', 'mich',
|
|
19
20
|
'nicht', 'noch', 'oder', 'sein', 'sind', 'soll', 'und', 'uns', 'von', 'was',
|
|
20
21
|
'wenn', 'werden', 'wie', 'with', 'that', 'this', 'from', 'have', 'into',
|
|
@@ -22,8 +23,36 @@ const STOP_WORDS = new Set([
|
|
|
22
23
|
]);
|
|
23
24
|
const REUSABLE_HEADING = /\b(rule|regel|condition|bedingung|countercheck|gegenprobe|trigger|ausloeser|auslöser)\b/iu;
|
|
24
25
|
|
|
26
|
+
const SEMANTIC_SIGNAL_RULES = Object.freeze([
|
|
27
|
+
['problem:reliability', /\b(?:error|failure|failed|broken|crash(?:ed)?|timeout|unavailable|corrupt(?:ed)?|dropped|missing|lost|fehler|scheiter\w*|absturz|ausfall|kaputt|defekt|fehlend|verloren|unerreichbar|abbruch)\b/iu],
|
|
28
|
+
['problem:delivery', /\b(?:deliver\w*|receiv\w*|message\w*|repl(?:y|ies)|inbox|outbox|send(?:ing|s|t)?|consum\w*|zustell\w*|empfang\w*|nachricht\w*|meldung\w*|senden|bekomm\w*|antwort\w*)\b/iu],
|
|
29
|
+
['problem:stagnation', /\b(?:loop\w*|repeat\w*|stuck|hang(?:ing)?|freeze|frozen|idle|no progress|stop(?:s|ped)? consuming|schleife\w*|wiederhol\w*|hang\w*|stillstand|leerlauf|kein fortschritt|taub)\b/iu],
|
|
30
|
+
['problem:performance', /\b(?:slow|latency|bottleneck|throughput|memory pressure|cpu|vram|langsam\w*|latenz|durchsatz|engpass|speicherdruck)\b/iu],
|
|
31
|
+
['problem:protocol', /\b(?:schema|contract|payload|protocol|format|version mismatch|manifest mismatch|vertrag|protokoll|versionskonflikt)\b/iu],
|
|
32
|
+
['problem:capability', /\b(?:capabilit\w*|missing tool|not available|unsupported|fahigkeit\w*|werkzeug fehlt|nicht verfugbar)\b/iu],
|
|
33
|
+
['area:orchestration', /\b(?:agent\w*|worker\w*|queue\w*|checkpoint\w*|heartbeat\w*|delegat\w*|owner\w*|responsib\w*|task\w*|turn\w*|busy|group\w*|channel\w*|arbeiter\w*|warteschlange\w*|prufpunkt\w*|herzschlag\w*|zustandig\w*|auftrag\w*|zug\w*|beschaftigt|gruppe\w*|gruppen\w*|kanal\w*)\b/iu],
|
|
34
|
+
['area:memory', /\b(?:memory|recall|remember\w*|context|history|resume|checkpoint|mnemo|gedachtnis|erinner\w*|kontext|verlauf|wiederaufnahme)\b/iu],
|
|
35
|
+
['area:release', /\b(?:release\w*|rollout\w*|update\w*|updater\w*|npm|package\w*|manifest\w*|version\w*|veroffentlich\w*|paket\w*|integrity|integritat)\b/iu],
|
|
36
|
+
['area:media', /\b(?:image\w*|video\w*|audio\w*|portrait\w*|render\w*|pixel\w*|media|bild\w*|foto\w*|gesicht\w*|stimme\w*)\b/iu],
|
|
37
|
+
['risk:validation', /\b(?:verif\w*|validat\w*|test\w*|check\w*|gate\w*|rollback\w*|canary|proof|evidence|sha(?:256|512)?|measur\w*|inspect\w*|(?:ge)?pruf\w*|gegenprobe\w*|beleg\w*|evidenz\w*|mess\w*|kontroll\w*)\b/iu],
|
|
38
|
+
['action:repair', /\b(?:fix\w*|repair\w*|restore\w*|recover\w*|reparier\w*|beheb\w*|wiederherstell\w*)\b/iu],
|
|
39
|
+
['action:investigate', /\b(?:inspect\w*|diagnos\w*|measure\w*|trace\w*|check\w*|(?:ge)?pruf\w*|mess\w*|untersuch\w*)\b/iu],
|
|
40
|
+
]);
|
|
41
|
+
|
|
25
42
|
function normalizeText(value) {
|
|
26
|
-
return String(value || '')
|
|
43
|
+
return String(value || '')
|
|
44
|
+
.normalize('NFKD')
|
|
45
|
+
.replace(/\p{M}/gu, '')
|
|
46
|
+
.replace(/\u00df/gu, 'ss')
|
|
47
|
+
.toLowerCase();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function semanticSignalTags(value) {
|
|
51
|
+
const normalized = normalizeText(value);
|
|
52
|
+
if (!normalized) return [];
|
|
53
|
+
return SEMANTIC_SIGNAL_RULES
|
|
54
|
+
.filter(([, pattern]) => pattern.test(normalized))
|
|
55
|
+
.map(([tag]) => tag);
|
|
27
56
|
}
|
|
28
57
|
|
|
29
58
|
function terms(value) {
|
|
@@ -100,15 +129,25 @@ function isReusableSection(section) {
|
|
|
100
129
|
return REUSABLE_HEADING.test(`${section.heading}\n${section.body}`);
|
|
101
130
|
}
|
|
102
131
|
|
|
103
|
-
function scoreSection(section, queryTerms) {
|
|
132
|
+
function scoreSection(section, queryTerms, queryTags) {
|
|
104
133
|
const heading = normalizeText(`${section.parent} ${section.heading}`);
|
|
105
134
|
const body = normalizeText(section.body);
|
|
106
135
|
let score = isReusableSection(section) ? 1 : 0;
|
|
136
|
+
let lexicalMatches = 0;
|
|
107
137
|
for (const term of queryTerms) {
|
|
108
|
-
if (heading.includes(term))
|
|
109
|
-
|
|
138
|
+
if (heading.includes(term)) {
|
|
139
|
+
score += 6;
|
|
140
|
+
lexicalMatches += 1;
|
|
141
|
+
}
|
|
142
|
+
if (body.includes(term)) {
|
|
143
|
+
score += 4;
|
|
144
|
+
lexicalMatches += 1;
|
|
145
|
+
}
|
|
110
146
|
}
|
|
111
|
-
|
|
147
|
+
const sectionTags = new Set(semanticSignalTags(`${heading}\n${body}`));
|
|
148
|
+
const semanticMatches = queryTags.filter((tag) => sectionTags.has(tag));
|
|
149
|
+
score += semanticMatches.length * 2;
|
|
150
|
+
return { lexicalMatches, score, semanticMatches };
|
|
112
151
|
}
|
|
113
152
|
|
|
114
153
|
function compactSection(section, maxChars) {
|
|
@@ -144,16 +183,24 @@ function selectRelevantMistakeSources(sources, query, options = {}) {
|
|
|
144
183
|
}))
|
|
145
184
|
));
|
|
146
185
|
const queryTerms = terms(query);
|
|
186
|
+
const queryTags = semanticSignalTags(query);
|
|
147
187
|
const ranked = sections.map((section) => {
|
|
148
188
|
const reusable = isReusableSection(section);
|
|
149
|
-
const score = scoreSection(section, queryTerms);
|
|
189
|
+
const { lexicalMatches, score, semanticMatches } = scoreSection(section, queryTerms, queryTags);
|
|
150
190
|
return {
|
|
151
191
|
...section,
|
|
152
|
-
|
|
192
|
+
lexicalMatches,
|
|
153
193
|
reusable,
|
|
154
194
|
score,
|
|
195
|
+
semanticMatches,
|
|
155
196
|
};
|
|
156
197
|
});
|
|
198
|
+
const hasLexicalMatch = ranked.some((section) => section.lexicalMatches > 0);
|
|
199
|
+
for (const section of ranked) {
|
|
200
|
+
section.matched = hasLexicalMatch
|
|
201
|
+
? section.lexicalMatches > 0
|
|
202
|
+
: section.semanticMatches.length > 0;
|
|
203
|
+
}
|
|
157
204
|
const hasMatch = ranked.some((section) => section.matched);
|
|
158
205
|
ranked.sort((left, right) => {
|
|
159
206
|
if (hasMatch && right.score !== left.score) return right.score - left.score;
|
|
@@ -188,6 +235,11 @@ function selectRelevantMistakeSources(sources, query, options = {}) {
|
|
|
188
235
|
selected.sort((left, right) => left.ordinal - right.ordinal);
|
|
189
236
|
const text = [header, ...selected.map((section) => section.rendered)].join('\n\n').slice(0, maxChars);
|
|
190
237
|
return {
|
|
238
|
+
selected: selected.map((section) => ({
|
|
239
|
+
heading: section.heading,
|
|
240
|
+
reference: normalizedSources[section.sourceIndex]?.reference || '',
|
|
241
|
+
semanticMatches: section.semanticMatches || [],
|
|
242
|
+
})),
|
|
191
243
|
selectedChars: text.length,
|
|
192
244
|
selectedSections: selected.length,
|
|
193
245
|
text,
|
|
@@ -209,6 +261,7 @@ module.exports = {
|
|
|
209
261
|
RECENT_USER_MESSAGES,
|
|
210
262
|
isLowInformationMistakeTurn,
|
|
211
263
|
recentUserText,
|
|
264
|
+
semanticSignalTags,
|
|
212
265
|
selectRelevantMistakeContent,
|
|
213
266
|
selectRelevantMistakeSources,
|
|
214
267
|
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
8
|
+
const DEFAULT_RETAIN_BYTES = 512 * 1024;
|
|
9
|
+
const MAX_MESSAGE_CHARS = 2048;
|
|
10
|
+
const MAX_STACK_CHARS = 8192;
|
|
11
|
+
const MAX_DETAIL_CHARS = 2048;
|
|
12
|
+
|
|
13
|
+
function runtimeExitLedgerPath(homeDir) {
|
|
14
|
+
return path.join(homeDir, 'diagnostics', 'runtime-exits.jsonl');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function replaceAllLiteral(value, needle, replacement) {
|
|
18
|
+
if (!needle) return value;
|
|
19
|
+
const lowerValue = process.platform === 'win32' ? value.toLowerCase() : value;
|
|
20
|
+
const lowerNeedle = process.platform === 'win32' ? needle.toLowerCase() : needle;
|
|
21
|
+
let result = '';
|
|
22
|
+
let cursor = 0;
|
|
23
|
+
for (;;) {
|
|
24
|
+
const index = lowerValue.indexOf(lowerNeedle, cursor);
|
|
25
|
+
if (index === -1) return `${result}${value.slice(cursor)}`;
|
|
26
|
+
result += `${value.slice(cursor, index)}${replacement}`;
|
|
27
|
+
cursor = index + needle.length;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function sanitizeExitText(input, maxChars = MAX_DETAIL_CHARS) {
|
|
32
|
+
let value = String(input ?? '');
|
|
33
|
+
const homes = new Set([
|
|
34
|
+
os.homedir(),
|
|
35
|
+
process.env.USERPROFILE,
|
|
36
|
+
process.env.HOME,
|
|
37
|
+
].filter((entry) => typeof entry === 'string' && entry.length > 2));
|
|
38
|
+
for (const home of homes) {
|
|
39
|
+
value = replaceAllLiteral(value, path.normalize(home), '$HOME');
|
|
40
|
+
value = replaceAllLiteral(value, home.replaceAll('\\', '/'), '$HOME');
|
|
41
|
+
}
|
|
42
|
+
value = value
|
|
43
|
+
.replace(/[A-Za-z]:\\Users\\[^\\\s"']+/giu, '$HOME')
|
|
44
|
+
.replace(/\/home\/[^/\s"']+/gu, '$HOME')
|
|
45
|
+
.replace(/(Authorization\s*:\s*Bearer\s+)[^\s,;]+/giu, '$1<redacted>')
|
|
46
|
+
.replace(/\bsk-[A-Za-z0-9_-]{10,}\b/gu, '<redacted>')
|
|
47
|
+
.replace(/\b\d{6,}:[A-Za-z0-9_-]{20,}\b/gu, '<redacted>')
|
|
48
|
+
.replace(/((?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|secret|password)\s*[=:]\s*)[^\s,;}]+/giu, '$1<redacted>')
|
|
49
|
+
.replace(/(https?:\/\/[^\s/:@]+:)[^\s/@]+@/giu, '$1<redacted>@');
|
|
50
|
+
return value.length <= maxChars ? value : `${value.slice(0, maxChars)}...[truncated]`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function normalizedError(error) {
|
|
54
|
+
if (error === undefined || error === null) return undefined;
|
|
55
|
+
if (error instanceof Error) {
|
|
56
|
+
return {
|
|
57
|
+
name: sanitizeExitText(error.name || error.constructor?.name || 'Error', 160),
|
|
58
|
+
message: sanitizeExitText(error.message || String(error), MAX_MESSAGE_CHARS),
|
|
59
|
+
stack: sanitizeExitText(error.stack || '', MAX_STACK_CHARS),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
name: typeof error === 'object' && typeof error.name === 'string'
|
|
64
|
+
? sanitizeExitText(error.name, 160)
|
|
65
|
+
: 'NonErrorRejection',
|
|
66
|
+
message: sanitizeExitText(error, MAX_MESSAGE_CHARS),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function finiteInteger(value) {
|
|
71
|
+
return Number.isInteger(value) ? value : undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function buildRuntimeExitRecord(input) {
|
|
75
|
+
const now = typeof input.now === 'function' ? input.now() : new Date();
|
|
76
|
+
const record = {
|
|
77
|
+
schemaVersion: 1,
|
|
78
|
+
ts: (now instanceof Date ? now : new Date(now)).toISOString(),
|
|
79
|
+
source: sanitizeExitText(input.source || 'unknown', 80),
|
|
80
|
+
kind: sanitizeExitText(input.kind || 'unknown', 120),
|
|
81
|
+
exitCode: finiteInteger(input.exitCode),
|
|
82
|
+
signal: input.signal ? sanitizeExitText(input.signal, 40) : undefined,
|
|
83
|
+
phase: input.phase ? sanitizeExitText(input.phase, 80) : undefined,
|
|
84
|
+
cliVersion: input.cliVersion ? sanitizeExitText(input.cliVersion, 80) : undefined,
|
|
85
|
+
profile: input.profile ? sanitizeExitText(input.profile, 120) : undefined,
|
|
86
|
+
sessionId: input.sessionId ? sanitizeExitText(input.sessionId, 240) : undefined,
|
|
87
|
+
pid: finiteInteger(input.pid ?? process.pid),
|
|
88
|
+
ppid: finiteInteger(input.ppid ?? process.ppid),
|
|
89
|
+
childPid: finiteInteger(input.childPid),
|
|
90
|
+
loaded: typeof input.loaded === 'boolean' ? input.loaded : undefined,
|
|
91
|
+
detail: input.detail ? sanitizeExitText(input.detail, MAX_DETAIL_CHARS) : undefined,
|
|
92
|
+
error: normalizedError(input.error),
|
|
93
|
+
};
|
|
94
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && value !== ''));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function trimLedger(filePath, maxBytes, retainBytes, incomingBytes) {
|
|
98
|
+
let size;
|
|
99
|
+
try {
|
|
100
|
+
size = fs.statSync(filePath).size;
|
|
101
|
+
} catch {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (size + incomingBytes <= maxBytes) return;
|
|
105
|
+
const contents = fs.readFileSync(filePath);
|
|
106
|
+
const keepFrom = Math.max(0, contents.length - Math.min(retainBytes, maxBytes - incomingBytes));
|
|
107
|
+
let lineStart = keepFrom;
|
|
108
|
+
if (lineStart > 0) {
|
|
109
|
+
const nextNewline = contents.indexOf(0x0a, lineStart);
|
|
110
|
+
lineStart = nextNewline === -1 ? contents.length : nextNewline + 1;
|
|
111
|
+
}
|
|
112
|
+
fs.writeFileSync(filePath, contents.subarray(lineStart), { mode: 0o600 });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function recordRuntimeExit(input = {}) {
|
|
116
|
+
try {
|
|
117
|
+
const homeDir = typeof input.homeDir === 'string' ? input.homeDir.trim() : '';
|
|
118
|
+
if (!homeDir) return false;
|
|
119
|
+
const filePath = runtimeExitLedgerPath(homeDir);
|
|
120
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
121
|
+
const line = `${JSON.stringify(buildRuntimeExitRecord(input))}\n`;
|
|
122
|
+
const incomingBytes = Buffer.byteLength(line);
|
|
123
|
+
const maxBytes = Math.max(1024, finiteInteger(input.maxBytes) ?? DEFAULT_MAX_BYTES);
|
|
124
|
+
const retainBytes = Math.max(0, finiteInteger(input.retainBytes) ?? DEFAULT_RETAIN_BYTES);
|
|
125
|
+
trimLedger(filePath, maxBytes, retainBytes, incomingBytes);
|
|
126
|
+
fs.appendFileSync(filePath, line, { encoding: 'utf8', mode: 0o600 });
|
|
127
|
+
try {
|
|
128
|
+
fs.chmodSync(filePath, 0o600);
|
|
129
|
+
} catch {}
|
|
130
|
+
return true;
|
|
131
|
+
} catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = {
|
|
137
|
+
DEFAULT_MAX_BYTES,
|
|
138
|
+
DEFAULT_RETAIN_BYTES,
|
|
139
|
+
buildRuntimeExitRecord,
|
|
140
|
+
recordRuntimeExit,
|
|
141
|
+
runtimeExitLedgerPath,
|
|
142
|
+
sanitizeExitText,
|
|
143
|
+
};
|
package/blun.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { createRequire } from "node:module";
|
|
|
8
8
|
import telegramConsoleStatusPolicy from "./bin/telegram-console-status-policy.cjs";
|
|
9
9
|
import cognitiveGoalAutostartPolicy from "./bin/cognitive-goal-autostart-policy.cjs";
|
|
10
10
|
import cognitiveGoalTimeTriggerController from "./bin/cognitive-goal-time-trigger-controller.cjs";
|
|
11
|
+
import runtimeExitLedger from "./bin/runtime-exit-ledger.cjs";
|
|
11
12
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
12
13
|
import * as fs$16 from "node:fs";
|
|
13
14
|
import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
@@ -40,6 +41,7 @@ import { pipeline as pipeline$1 } from "node:stream/promises";
|
|
|
40
41
|
const { writeTelegramConsoleStatus } = telegramConsoleStatusPolicy;
|
|
41
42
|
const { goalAutostartDecision, goalContinuationDecision } = cognitiveGoalAutostartPolicy;
|
|
42
43
|
const { GoalTimeTriggerController } = cognitiveGoalTimeTriggerController;
|
|
44
|
+
const { recordRuntimeExit } = runtimeExitLedger;
|
|
43
45
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
44
46
|
import { StringDecoder } from "node:string_decoder";
|
|
45
47
|
import co from "node:assert";
|
|
@@ -516808,6 +516810,17 @@ var BlunTUI = class {
|
|
|
516808
516810
|
if (process.platform !== "win32") signals.push("SIGHUP");
|
|
516809
516811
|
for (const signal of signals) {
|
|
516810
516812
|
const handler = () => {
|
|
516813
|
+
recordRuntimeExit({
|
|
516814
|
+
homeDir: process.env["BLUN_HOME"],
|
|
516815
|
+
source: "core",
|
|
516816
|
+
kind: "signal",
|
|
516817
|
+
exitCode: signal === "SIGTERM" ? 143 : 129,
|
|
516818
|
+
signal,
|
|
516819
|
+
phase: "runtime",
|
|
516820
|
+
cliVersion: process.env["BLUN_PUBLIC_PACKAGE_VERSION"],
|
|
516821
|
+
profile: process.env["BLUN_PROFILE"],
|
|
516822
|
+
sessionId: this.getCurrentSessionId()
|
|
516823
|
+
});
|
|
516811
516824
|
if (signal === "SIGHUP") {
|
|
516812
516825
|
this.emergencyTerminalExit();
|
|
516813
516826
|
return;
|
|
@@ -516824,7 +516837,20 @@ var BlunTUI = class {
|
|
|
516824
516837
|
});
|
|
516825
516838
|
}
|
|
516826
516839
|
const terminalErrorHandler = (error) => {
|
|
516827
|
-
if (isDeadTerminalError(error))
|
|
516840
|
+
if (isDeadTerminalError(error)) {
|
|
516841
|
+
recordRuntimeExit({
|
|
516842
|
+
homeDir: process.env["BLUN_HOME"],
|
|
516843
|
+
source: "core",
|
|
516844
|
+
kind: "dead-terminal",
|
|
516845
|
+
exitCode: 129,
|
|
516846
|
+
phase: "runtime",
|
|
516847
|
+
cliVersion: process.env["BLUN_PUBLIC_PACKAGE_VERSION"],
|
|
516848
|
+
profile: process.env["BLUN_PROFILE"],
|
|
516849
|
+
sessionId: this.getCurrentSessionId(),
|
|
516850
|
+
error
|
|
516851
|
+
});
|
|
516852
|
+
this.emergencyTerminalExit();
|
|
516853
|
+
}
|
|
516828
516854
|
};
|
|
516829
516855
|
process.stdout.on("error", terminalErrorHandler);
|
|
516830
516856
|
process.stderr.on("error", terminalErrorHandler);
|
|
@@ -519588,6 +519614,15 @@ async function runShell(opts, version) {
|
|
|
519588
519614
|
const trackLifecycle = (event, properties) => {
|
|
519589
519615
|
trackLifecycleForSession(tui.getCurrentSessionId(), event, properties);
|
|
519590
519616
|
};
|
|
519617
|
+
const recordShellExit = (entry) => recordRuntimeExit({
|
|
519618
|
+
homeDir: process.env["BLUN_HOME"] ?? telemetryBootstrap.homeDir,
|
|
519619
|
+
source: "core",
|
|
519620
|
+
phase: "runtime",
|
|
519621
|
+
cliVersion: version,
|
|
519622
|
+
profile: process.env["BLUN_PROFILE"],
|
|
519623
|
+
sessionId: tui.getCurrentSessionId(),
|
|
519624
|
+
...entry
|
|
519625
|
+
});
|
|
519591
519626
|
let savedStty;
|
|
519592
519627
|
try {
|
|
519593
519628
|
const saved = execSync("stty -g", {
|
|
@@ -519621,12 +519656,22 @@ async function runShell(opts, version) {
|
|
|
519621
519656
|
process.exit(exitCode);
|
|
519622
519657
|
};
|
|
519623
519658
|
const onUncaughtException = (error) => {
|
|
519659
|
+
recordShellExit({
|
|
519660
|
+
kind: "uncaught-exception",
|
|
519661
|
+
exitCode: 1,
|
|
519662
|
+
error
|
|
519663
|
+
});
|
|
519624
519664
|
try {
|
|
519625
519665
|
log.error("uncaughtException, restoring terminal and exiting", { error: String(error) });
|
|
519626
519666
|
} catch {}
|
|
519627
519667
|
emergencyExit(1);
|
|
519628
519668
|
};
|
|
519629
519669
|
const onUnhandledRejection = (reason) => {
|
|
519670
|
+
recordShellExit({
|
|
519671
|
+
kind: "unhandled-rejection",
|
|
519672
|
+
exitCode: 1,
|
|
519673
|
+
error: reason
|
|
519674
|
+
});
|
|
519630
519675
|
try {
|
|
519631
519676
|
log.error("unhandledRejection, restoring terminal and exiting", { reason: String(reason) });
|
|
519632
519677
|
} catch {}
|
|
@@ -519641,6 +519686,10 @@ async function runShell(opts, version) {
|
|
|
519641
519686
|
tui.onExit = async (exitCode = 0) => {
|
|
519642
519687
|
const sessionId = tui.getCurrentSessionId();
|
|
519643
519688
|
const hasContent = tui.hasSessionContent();
|
|
519689
|
+
recordShellExit({
|
|
519690
|
+
kind: "normal-exit",
|
|
519691
|
+
exitCode
|
|
519692
|
+
});
|
|
519644
519693
|
setCrashPhase("shutdown");
|
|
519645
519694
|
trackLifecycle("exit", { duration_ms: Date.now() - startedAt });
|
|
519646
519695
|
await shutdownTelemetry({ timeoutMs: CLI_SHUTDOWN_TIMEOUT_MS });
|
|
@@ -519671,6 +519720,12 @@ async function runShell(opts, version) {
|
|
|
519671
519720
|
...tui.getStartupPhaseMs()
|
|
519672
519721
|
});
|
|
519673
519722
|
} catch (error) {
|
|
519723
|
+
recordShellExit({
|
|
519724
|
+
kind: "startup-failure",
|
|
519725
|
+
exitCode: 1,
|
|
519726
|
+
phase: "startup",
|
|
519727
|
+
error
|
|
519728
|
+
});
|
|
519674
519729
|
removeCrashHandlers();
|
|
519675
519730
|
setCrashPhase("shutdown");
|
|
519676
519731
|
trackLifecycle("exit", { duration_ms: Date.now() - startedAt });
|