blun-king-cli 9.1.550 → 9.1.562
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LIESMICH.txt +2 -2
- package/README.md +1 -1
- package/agent-spine-plugin/scripts/check-hosts.js +196 -0
- package/bin/compaction-transaction-policy.cjs +122 -0
- package/bin/default-model-output-budget-policy.cjs +28 -0
- package/bin/file-observation-policy.cjs +133 -0
- package/bin/launcher-runtime.js +0 -1
- package/bin/micro-compaction-policy.cjs +64 -0
- package/bin/mnemo-connect-heartbeat.cjs +1 -3
- package/bin/retry-checkpoint-policy.cjs +13 -0
- package/bin/session-checkpoint-policy.cjs +25 -0
- package/bin/startup-preferences.cjs +1 -0
- package/bin/tool-file-persistence.cjs +141 -0
- package/bin/tool-result-offload-policy.cjs +12 -33
- package/bin/turn-thinking-policy.cjs +2 -26
- package/bin/update-notice.js +16 -0
- package/blun.mjs +482 -170
- package/package.json +2 -1
- package/telegram-plugin/bin/telegram-mnemo-capture.cjs +1 -3
- package/bin/empty-response-retry-policy.cjs +0 -29
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { randomBytes } = require('node:crypto');
|
|
4
|
+
const fs = require('node:fs/promises');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const WINDOWS_RENAME_RETRY_CODES = new Set(['EACCES', 'EBUSY', 'EPERM']);
|
|
8
|
+
const DEFAULT_WINDOWS_RENAME_DELAYS_MS = Object.freeze([10, 25, 50, 100]);
|
|
9
|
+
|
|
10
|
+
function isAbortError(error) {
|
|
11
|
+
return error instanceof Error && error.name === 'AbortError';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function throwIfAborted(signal) {
|
|
15
|
+
if (!signal?.aborted) return;
|
|
16
|
+
const error = new Error('Atomic tool write aborted before publication.');
|
|
17
|
+
error.name = 'AbortError';
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isMissing(error) {
|
|
22
|
+
return error?.code === 'ENOENT' || error?.code === 'ENOTDIR';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function existingFileMode(filePath, statFile) {
|
|
26
|
+
try {
|
|
27
|
+
const info = await statFile(filePath);
|
|
28
|
+
if (!info.isFile()) throw Object.assign(new Error(`Cannot replace non-file target: ${filePath}`), { code: 'EISDIR' });
|
|
29
|
+
return typeof info.mode === 'number' ? info.mode & 0o777 : undefined;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (isMissing(error)) return undefined;
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function resolvePublicationPath(filePath, operations) {
|
|
37
|
+
try {
|
|
38
|
+
return await operations.realpathFile(filePath);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (!isMissing(error)) throw error;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const linkInfo = await operations.lstatFile(filePath);
|
|
45
|
+
if (linkInfo.isSymbolicLink()) {
|
|
46
|
+
throw Object.assign(new Error(`Refused atomic replacement through dangling symbolic link: ${filePath}`), { code: 'ELOOP' });
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (!isMissing(error)) throw error;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const realParent = await operations.realpathFile(path.dirname(filePath));
|
|
53
|
+
return path.join(realParent, path.basename(filePath));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function renameWithWindowsRetry(source, target, options) {
|
|
57
|
+
const delays = options.platform === 'win32'
|
|
58
|
+
? options.windowsRenameDelaysMs
|
|
59
|
+
: [];
|
|
60
|
+
let attempt = 0;
|
|
61
|
+
while (true) {
|
|
62
|
+
try {
|
|
63
|
+
await options.renameFile(source, target);
|
|
64
|
+
return;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const delayMs = delays[attempt];
|
|
67
|
+
if (delayMs === undefined || !WINDOWS_RENAME_RETRY_CODES.has(error?.code)) throw error;
|
|
68
|
+
attempt += 1;
|
|
69
|
+
throwIfAborted(options.signal);
|
|
70
|
+
await options.sleep(delayMs);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function writeToolTextAtomic(filePath, content, options = {}) {
|
|
76
|
+
if (typeof filePath !== 'string' || filePath.length === 0) throw new TypeError('filePath must be a non-empty string');
|
|
77
|
+
if (typeof content !== 'string' && !Buffer.isBuffer(content)) throw new TypeError('content must be a string or Buffer');
|
|
78
|
+
|
|
79
|
+
const openFile = options.openFile || fs.open;
|
|
80
|
+
const renameFile = options.renameFile || fs.rename;
|
|
81
|
+
const unlinkFile = options.unlinkFile || fs.unlink;
|
|
82
|
+
const statFile = options.statFile || fs.stat;
|
|
83
|
+
const lstatFile = options.lstatFile || fs.lstat;
|
|
84
|
+
const realpathFile = options.realpathFile || fs.realpath;
|
|
85
|
+
const syncHandle = options.syncHandle || ((handle) => handle.sync());
|
|
86
|
+
const sleep = options.sleep || ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
|
|
87
|
+
const signal = options.signal;
|
|
88
|
+
const platform = options.platform || process.platform;
|
|
89
|
+
const windowsRenameDelaysMs = options.windowsRenameDelaysMs || DEFAULT_WINDOWS_RENAME_DELAYS_MS;
|
|
90
|
+
|
|
91
|
+
throwIfAborted(signal);
|
|
92
|
+
const publicationPath = await resolvePublicationPath(filePath, { lstatFile, realpathFile });
|
|
93
|
+
const mode = await existingFileMode(publicationPath, statFile);
|
|
94
|
+
const suffix = `${process.pid}.${randomBytes(6).toString('hex')}`;
|
|
95
|
+
const temporaryPath = path.join(path.dirname(publicationPath), `.${path.basename(publicationPath)}.${suffix}.tmp`);
|
|
96
|
+
let handle;
|
|
97
|
+
let published = false;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
handle = await openFile(temporaryPath, 'wx', mode ?? 0o666);
|
|
101
|
+
await handle.writeFile(content, typeof content === 'string' ? { encoding: 'utf8', signal } : { signal });
|
|
102
|
+
await syncHandle(handle);
|
|
103
|
+
if (mode !== undefined && platform !== 'win32') await handle.chmod(mode);
|
|
104
|
+
await handle.close();
|
|
105
|
+
handle = undefined;
|
|
106
|
+
|
|
107
|
+
throwIfAborted(signal);
|
|
108
|
+
await renameWithWindowsRetry(temporaryPath, publicationPath, {
|
|
109
|
+
platform,
|
|
110
|
+
renameFile,
|
|
111
|
+
signal,
|
|
112
|
+
sleep,
|
|
113
|
+
windowsRenameDelaysMs,
|
|
114
|
+
});
|
|
115
|
+
published = true;
|
|
116
|
+
return { bytesWritten: Buffer.byteLength(content) };
|
|
117
|
+
} finally {
|
|
118
|
+
if (handle !== undefined) {
|
|
119
|
+
try {
|
|
120
|
+
await handle.close();
|
|
121
|
+
} catch {}
|
|
122
|
+
}
|
|
123
|
+
if (!published) {
|
|
124
|
+
try {
|
|
125
|
+
await unlinkFile(temporaryPath);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (!isMissing(error)) {
|
|
128
|
+
// The primary write error remains authoritative; stale temp names are unique and never read.
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
DEFAULT_WINDOWS_RENAME_DELAYS_MS,
|
|
137
|
+
WINDOWS_RENAME_RETRY_CODES,
|
|
138
|
+
renameWithWindowsRetry,
|
|
139
|
+
resolvePublicationPath,
|
|
140
|
+
writeToolTextAtomic,
|
|
141
|
+
};
|
|
@@ -28,8 +28,10 @@ function hasToolResultOffloadPressure(options = {}) {
|
|
|
28
28
|
return hasContextPressure(options);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function shouldOffloadToolResult(textLength) {
|
|
32
|
-
return Number.isFinite(textLength)
|
|
31
|
+
function shouldOffloadToolResult(textLength, options = {}) {
|
|
32
|
+
return Number.isFinite(textLength)
|
|
33
|
+
&& textLength > TOOL_RESULT_MAX_CHARS
|
|
34
|
+
&& hasToolResultOffloadPressure(options);
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
function shouldKeepFreshToolResult(toolName) {
|
|
@@ -165,33 +167,8 @@ function compactPersistedToolResultReference(content) {
|
|
|
165
167
|
}
|
|
166
168
|
|
|
167
169
|
function compactHistoricalSuccessfulToolResults(messages, options = {}) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const recentStart = Math.max(0, messages.length - TOOL_RESULT_SUCCESS_KEEP_RECENT_MESSAGES);
|
|
172
|
-
const freshIds = freshToolResultIds(messages);
|
|
173
|
-
let changed = false;
|
|
174
|
-
const projected = messages.map((message, index) => {
|
|
175
|
-
if (
|
|
176
|
-
index >= recentStart
|
|
177
|
-
|| message?.role !== 'tool'
|
|
178
|
-
|| freshIds.has(message.toolCallId)
|
|
179
|
-
|| message.isError === true
|
|
180
|
-
|| !Array.isArray(message.content)
|
|
181
|
-
|| isPersistedToolResultReference(message.content)
|
|
182
|
-
|| !message.content.every((part) => part?.type === 'text' && typeof part.text === 'string')
|
|
183
|
-
) return message;
|
|
184
|
-
|
|
185
|
-
const textChars = message.content.reduce((total, part) => total + part.text.length, 0);
|
|
186
|
-
if (textChars <= TOOL_RESULT_HISTORICAL_SUCCESS_MARKER.length) return message;
|
|
187
|
-
changed = true;
|
|
188
|
-
return {
|
|
189
|
-
...message,
|
|
190
|
-
content: [{ type: 'text', text: TOOL_RESULT_HISTORICAL_SUCCESS_MARKER }],
|
|
191
|
-
};
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
return changed ? projected : messages;
|
|
170
|
+
void options;
|
|
171
|
+
return messages;
|
|
195
172
|
}
|
|
196
173
|
|
|
197
174
|
function toolCallSignaturesById(messages) {
|
|
@@ -280,10 +257,12 @@ function dedupeRepeatedSuccessfulToolResults(sourceMessages, projectedMessages =
|
|
|
280
257
|
...projectedMessage,
|
|
281
258
|
content: [{ type: 'text', text: reference }],
|
|
282
259
|
};
|
|
283
|
-
projected[newest.index]
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
260
|
+
if (projected[newest.index] !== sourceMessages[newest.index]) {
|
|
261
|
+
projected[newest.index] = {
|
|
262
|
+
...projected[newest.index],
|
|
263
|
+
content: sourceMessages[newest.index].content,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
287
266
|
changed = true;
|
|
288
267
|
}
|
|
289
268
|
|
|
@@ -7,9 +7,6 @@ const BOSNIAN_STANDALONE_CHAT = /^(?:zdravo|pozdrav|hvala|ćao|cao)[.!?]*$/iu;
|
|
|
7
7
|
const IDENTITY_CHAT = /^(?:wer bist du|who are you|wie geht(?: es dir)?|how are you|na|kako si|kako je king|ko si ti|ko stoji iza tebe)[.!?]*$/iu;
|
|
8
8
|
const STATUS_ONLY_CHECK_IN = /(?:\bstandabfrage\b|\bstatusabfrage\b|\bkurzes?\s+update\b|\bwo\s+stehst\s+du\b|\bwie\s+weit\s+bist\s+du\b|\bwhere\s+are\s+you\b|\bquick\s+status\b)/iu;
|
|
9
9
|
const STATUS_FOLLOW_UP_ACTION = /\b(?:aendere|arbeite|baue|build|change|delete|deploy|deploye|fahr|fix|fixe|implement|implementiere|install|installiere|loesche|mach|patch|pruefe|repariere|run|schreibe|setze|start|starte|stop|stoppe|test|teste|write)\b/iu;
|
|
10
|
-
const STANDALONE_CHAT_COMPLETION_TOKENS = 1024;
|
|
11
|
-
const ADAPTIVE_LOW_COMPLETION_TOKENS = 4096;
|
|
12
|
-
const STANDARD_TURN_MAX_COMPLETION_TOKENS = 24_576;
|
|
13
10
|
|
|
14
11
|
function selectThinkingEffortForTurn(text, originKind) {
|
|
15
12
|
if (originKind !== "user") return undefined;
|
|
@@ -45,25 +42,8 @@ function selectThinkingEffortForWorkStep(_stepNumber, _previousToolOutcome) {
|
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
function capCompletionBudgetForAdaptiveEffort(budget, thinkingEffort) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const adaptiveCap = thinkingEffort === "off"
|
|
51
|
-
? STANDALONE_CHAT_COMPLETION_TOKENS
|
|
52
|
-
: ADAPTIVE_LOW_COMPLETION_TOKENS;
|
|
53
|
-
return {
|
|
54
|
-
...budget,
|
|
55
|
-
hardCap: Math.min(
|
|
56
|
-
configuredCap ?? adaptiveCap,
|
|
57
|
-
adaptiveCap,
|
|
58
|
-
),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function capTurnCompletionTokens(maxOutputSize) {
|
|
63
|
-
if (!Number.isFinite(maxOutputSize) || maxOutputSize <= 0) {
|
|
64
|
-
return STANDARD_TURN_MAX_COMPLETION_TOKENS;
|
|
65
|
-
}
|
|
66
|
-
return Math.min(Math.floor(maxOutputSize), STANDARD_TURN_MAX_COMPLETION_TOKENS);
|
|
45
|
+
void thinkingEffort;
|
|
46
|
+
return budget;
|
|
67
47
|
}
|
|
68
48
|
|
|
69
49
|
function selectThinkingEffortForBufferedSteer(text, originKind) {
|
|
@@ -77,12 +57,8 @@ function selectThinkingEffortForBufferedSteer(text, originKind) {
|
|
|
77
57
|
|
|
78
58
|
module.exports = {
|
|
79
59
|
ACTIONABLE_PROMPT,
|
|
80
|
-
ADAPTIVE_LOW_COMPLETION_TOKENS,
|
|
81
60
|
EXPLICIT_THINKING_INTENT,
|
|
82
|
-
STANDALONE_CHAT_COMPLETION_TOKENS,
|
|
83
|
-
STANDARD_TURN_MAX_COMPLETION_TOKENS,
|
|
84
61
|
capCompletionBudgetForAdaptiveEffort,
|
|
85
|
-
capTurnCompletionTokens,
|
|
86
62
|
selectThinkingEffortForBufferedSteer,
|
|
87
63
|
selectThinkingEffortForWorkStep,
|
|
88
64
|
selectThinkingEffortForTurn,
|
package/bin/update-notice.js
CHANGED
|
@@ -82,6 +82,15 @@ const ENDPOINT_LIMITS = new Map([
|
|
|
82
82
|
[FALLBACK_MANIFEST_URL, 64 * 1024],
|
|
83
83
|
]);
|
|
84
84
|
|
|
85
|
+
function isInternalPackagePinned(packageRoot) {
|
|
86
|
+
try {
|
|
87
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
88
|
+
return manifest?.blunUpdateChannel === 'internal';
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
function parseSemver(value) {
|
|
86
95
|
if (typeof value !== 'string' || value.length > 128) return undefined;
|
|
87
96
|
const match = SEMVER_PATTERN.exec(value);
|
|
@@ -1393,6 +1402,12 @@ async function runUpdateFlow(options, explicitUpdate) {
|
|
|
1393
1402
|
const now = (options.now || Date.now)();
|
|
1394
1403
|
|
|
1395
1404
|
const packageRoot = path.resolve(options.packageRoot || path.resolve(__dirname, '..'));
|
|
1405
|
+
if (isInternalPackagePinned(packageRoot)) {
|
|
1406
|
+
if (explicitUpdate) explicitNoTarget(stdout, 'current', currentVersion, uiLocale);
|
|
1407
|
+
return explicitUpdate
|
|
1408
|
+
? { kind: 'current', reason: 'internal_channel' }
|
|
1409
|
+
: { kind: 'continue', reason: 'internal_channel' };
|
|
1410
|
+
}
|
|
1396
1411
|
let leaseResult;
|
|
1397
1412
|
const ownsNoticeLease = options.noticeLease === undefined;
|
|
1398
1413
|
if (ownsNoticeLease) {
|
|
@@ -1632,6 +1647,7 @@ module.exports = {
|
|
|
1632
1647
|
compareSemver,
|
|
1633
1648
|
createInstallInvocation,
|
|
1634
1649
|
installPinnedVersion,
|
|
1650
|
+
isInternalPackagePinned,
|
|
1635
1651
|
preparePinnedInstaller,
|
|
1636
1652
|
isInteractiveUpdateStart,
|
|
1637
1653
|
loadReleaseSources,
|